init: 初始化项目

This commit is contained in:
0264408
2026-03-10 16:26:48 +08:00
commit 57e0ef2cf6
79 changed files with 8943 additions and 0 deletions

87
internal/storage/local.go Normal file
View File

@@ -0,0 +1,87 @@
package storage
import (
"fmt"
"io"
"os"
"path/filepath"
)
// LocalStorage 本地文件系统存储实现
type LocalStorage struct {
basePath string // 文件存储的根目录
baseURL string // 文件访问的 URL 前缀
}
// NewLocalStorage 创建本地存储实例
func NewLocalStorage(basePath, baseURL string) (*LocalStorage, error) {
// 确保存储目录存在
if err := os.MkdirAll(basePath, 0755); err != nil {
return nil, fmt.Errorf("failed to create storage directory: %w", err)
}
return &LocalStorage{
basePath: basePath,
baseURL: baseURL,
}, nil
}
// Save 保存文件到本地
func (s *LocalStorage) Save(filename string, content io.Reader) (string, error) {
// 构建完整的文件路径
fullPath := filepath.Join(s.basePath, filename)
// 确保目标目录存在
dir := filepath.Dir(fullPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return "", fmt.Errorf("failed to create directory: %w", err)
}
// 创建文件
file, err := os.Create(fullPath)
if err != nil {
return "", fmt.Errorf("failed to create file: %w", err)
}
defer file.Close()
// 复制内容
if _, err := io.Copy(file, content); err != nil {
// 如果保存失败,尝试删除文件
os.Remove(fullPath)
return "", fmt.Errorf("failed to write file: %w", err)
}
// 返回相对路径(存储在数据库中)
return filename, nil
}
// Delete 删除本地文件
func (s *LocalStorage) Delete(path string) error {
fullPath := filepath.Join(s.basePath, path)
if err := os.Remove(fullPath); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete file: %w", err)
}
return nil
}
// GetURL 获取文件的访问 URL
func (s *LocalStorage) GetURL(path string) string {
if path == "" {
return ""
}
// 将路径中的反斜杠替换为正斜杠Windows 兼容)
path = filepath.ToSlash(path)
return s.baseURL + "/" + path
}
// Exists 检查文件是否存在
func (s *LocalStorage) Exists(path string) bool {
fullPath := filepath.Join(s.basePath, path)
_, err := os.Stat(fullPath)
return err == nil
}
// GetFullPath 获取文件的完整本地路径
func (s *LocalStorage) GetFullPath(path string) string {
return filepath.Join(s.basePath, path)
}