package storage import ( "context" "fmt" "path/filepath" "strings" "time" "github.com/google/uuid" "github.com/break/junhong_cmp_fiber/pkg/config" "github.com/break/junhong_cmp_fiber/pkg/errors" ) type Service struct { provider Provider config *config.StorageConfig } func NewService(provider Provider, cfg *config.StorageConfig) *Service { return &Service{ provider: provider, config: cfg, } } func (s *Service) GenerateFileKey(purpose, fileName string) (string, error) { mapping, ok := PurposeMappings[purpose] if !ok { return "", errors.New(errors.CodeInvalidParam, "不支持的文件用途: %s", purpose) } ext := filepath.Ext(fileName) if ext == "" { ext = ".bin" } now := time.Now() id := uuid.New().String() key := fmt.Sprintf("%s/%04d/%02d/%02d/%s%s", mapping.Prefix, now.Year(), now.Month(), now.Day(), id, strings.ToLower(ext), ) return key, nil } func (s *Service) GetUploadURL(ctx context.Context, purpose, fileName, contentType string) (*PresignResult, error) { fileKey, err := s.GenerateFileKey(purpose, fileName) if err != nil { return nil, err } if contentType == "" { if mapping, ok := PurposeMappings[purpose]; ok && mapping.ContentType != "" { contentType = mapping.ContentType } else { contentType = "application/octet-stream" } } expires := s.config.Presign.UploadExpires if expires == 0 { expires = 15 * time.Minute } url, err := s.provider.GetUploadURL(ctx, fileKey, contentType, expires) if err != nil { return nil, err } return &PresignResult{ URL: url, FileKey: fileKey, ExpiresIn: int(expires.Seconds()), }, nil } func (s *Service) GetDownloadURL(ctx context.Context, fileKey string) (*PresignResult, error) { expires := s.config.Presign.DownloadExpires if expires == 0 { expires = 24 * time.Hour } url, err := s.provider.GetDownloadURL(ctx, fileKey, expires) if err != nil { return nil, err } return &PresignResult{ URL: url, FileKey: fileKey, ExpiresIn: int(expires.Seconds()), }, nil } func (s *Service) DownloadToTemp(ctx context.Context, fileKey string) (string, func(), error) { return s.provider.DownloadToTemp(ctx, fileKey) } func (s *Service) Provider() Provider { return s.provider } func (s *Service) Bucket() string { return s.config.S3.Bucket }