package storage import ( "context" "fmt" "io" "net/http" "net/url" "strings" "github.com/tencentyun/cos-go-sdk-v5" "gotest/internal/config" ) // COSStorage 腾讯云 COS 对象存储实现 type COSStorage struct { client *cos.Client baseURL string } // NewCOSStorage 创建 COS 存储实例 func NewCOSStorage(cfg *config.COSConfig) (*COSStorage, error) { // 拼接 bucket 访问地址: https://.cos..myqcloud.com bucketURL := fmt.Sprintf("https://%s.cos.%s.myqcloud.com", cfg.Bucket, cfg.Region) u, err := url.Parse(bucketURL) if err != nil { return nil, fmt.Errorf("解析 COS bucket 地址失败: %w", err) } baseURL := &cos.BaseURL{BucketURL: u} client := cos.NewClient(baseURL, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: cfg.SecretID, SecretKey: cfg.SecretKey, }, }) return &COSStorage{ client: client, baseURL: cfg.BaseURL, }, nil } // Upload 上传文件到 COS func (s *COSStorage) Upload(key string, reader io.Reader, contentType string) (string, error) { ctx := context.Background() opt := &cos.ObjectPutOptions{ ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{ ContentType: contentType, }, } _, err := s.client.Object.Put(ctx, key, reader, opt) if err != nil { return "", fmt.Errorf("上传文件到 COS 失败: %w", err) } return s.GetURL(key), nil } // Delete 删除 COS 中的文件 func (s *COSStorage) Delete(key string) error { ctx := context.Background() _, err := s.client.Object.Delete(ctx, key, nil) return err } // GetURL 获取 COS 文件访问 URL // 优先使用 BaseURL 拼接,为空时回退到 bucket 地址 func (s *COSStorage) GetURL(key string) string { base := strings.TrimRight(s.baseURL, "/") if base == "" { base = strings.TrimRight(s.client.BaseURL.BucketURL.String(), "/") } return base + "/" + key }