package storage import ( "context" "fmt" "io" "time" "git.toowon.com/jimmy/go-common/config" ) // Storage 存储接口 type Storage interface { // Upload 上传文件 // ctx: 上下文 // objectKey: 对象键(文件路径) // reader: 文件内容 // contentType: 文件类型(可选) Upload(ctx context.Context, objectKey string, reader io.Reader, contentType ...string) error // GetURL 获取文件访问URL // objectKey: 对象键 // expires: 过期时间(秒),0表示永久有效 GetURL(objectKey string, expires int64) (string, error) // Delete 删除文件 Delete(ctx context.Context, objectKey string) error // Exists 检查文件是否存在 Exists(ctx context.Context, objectKey string) (bool, error) // GetObject 获取文件内容 GetObject(ctx context.Context, objectKey string) (io.ReadCloser, error) } // StorageType 存储类型 type StorageType string const ( StorageTypeOSS StorageType = "oss" StorageTypeMinIO StorageType = "minio" ) // NewStorage 创建存储实例 // storageType: 存储类型(oss或minio) // cfg: 配置对象 func NewStorage(storageType StorageType, cfg *config.Config) (Storage, error) { switch storageType { case StorageTypeOSS: ossConfig := cfg.GetOSS() if ossConfig == nil { return nil, fmt.Errorf("OSS config is nil") } return NewOSSStorage(ossConfig) case StorageTypeMinIO: minioConfig := cfg.GetMinIO() if minioConfig == nil { return nil, fmt.Errorf("MinIO config is nil") } return NewMinIOStorage(minioConfig) default: return nil, fmt.Errorf("unsupported storage type: %s", storageType) } } // UploadResult 上传结果 type UploadResult struct { // ObjectKey 对象键(文件路径) ObjectKey string `json:"objectKey"` // URL 文件访问URL URL string `json:"url"` // Size 文件大小(字节) Size int64 `json:"size"` // ContentType 文件类型 ContentType string `json:"contentType"` // UploadTime 上传时间 UploadTime time.Time `json:"uploadTime"` } // GenerateObjectKey 生成对象键 // prefix: 前缀(如 "images/", "files/") // filename: 文件名 func GenerateObjectKey(prefix, filename string) string { if prefix == "" { return filename } if prefix[len(prefix)-1] != '/' { prefix += "/" } return prefix + filename } // GenerateObjectKeyWithDate 生成带日期的对象键 // prefix: 前缀 // filename: 文件名 // 格式: prefix/YYYY/MM/DD/filename func GenerateObjectKeyWithDate(prefix, filename string) string { now := time.Now() datePath := fmt.Sprintf("%d/%02d/%02d", now.Year(), now.Month(), now.Day()) return GenerateObjectKey(prefix+"/"+datePath, filename) }