package common import ( "context" "fmt" "io" "net/http" "net/url" "path" "strings" "time" "bindbox-game/configs" cos "github.com/tencentyun/cos-go-sdk-v5" ) type Service interface { UploadImage(ctx context.Context, filename string, reader io.Reader, contentType string) (string, error) } type service struct { client *cos.Client bucketURL string publicBase string } func New() Service { cfg := configs.Get() bucket := cfg.COS.Bucket region := cfg.COS.Region base := fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, region) bu, _ := url.Parse(base) client := cos.NewClient(&cos.BaseURL{BucketURL: bu}, &http.Client{ Transport: &cos.AuthorizationTransport{SecretID: cfg.COS.SecretID, SecretKey: cfg.COS.SecretKey}, }) return &service{client: client, bucketURL: base, publicBase: strings.TrimSpace(cfg.COS.BaseURL)} } func (s *service) UploadImage(ctx context.Context, filename string, reader io.Reader, contentType string) (string, error) { date := time.Now().Format("2006/01/02") ext := strings.ToLower(path.Ext(filename)) if ext == "" { ext = ".jpg" } ct := contentType if ct == "" || ct == "application/octet-stream" { switch ext { case ".jpg", ".jpeg": ct = "image/jpeg" case ".png": ct = "image/png" case ".gif": ct = "image/gif" case ".webp": ct = "image/webp" case ".bmp": ct = "image/bmp" default: ct = "application/octet-stream" } } key := fmt.Sprintf("images/%s/%d%s", date, time.Now().UnixNano(), ext) _, err := s.client.Object.Put(ctx, key, reader, &cos.ObjectPutOptions{ ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{ ContentType: ct, }, ACLHeaderOptions: &cos.ACLHeaderOptions{ XCosACL: "public-read", }, }) if err != nil { return "", err } if s.publicBase != "" { return strings.TrimRight(s.publicBase, "/") + "/" + key, nil } return s.bucketURL + "/" + key, nil }