package tencent import ( "bytes" "context" "errors" "io" "net/http" "net/url" "strings" "time" "github.com/ssgo/u" "github.com/tencentyun/cos-go-sdk-v5" sts "github.com/tencentyun/qcloud-cos-sts-sdk/go" ) type Cos struct { client *cos.Client baseUrl string bucket string appId string region string } func GetCos(bucket string) (*Cos, error) { bConf := conf.Cos[bucket] if bConf == nil { return nil, errors.New("bucket not found") } a := strings.Split(bConf.Bucket, "-") baseUrl := "https://" + bConf.Bucket + ".cos." + bConf.Region + ".myqcloud.com" bUrl, _ := url.Parse(baseUrl) return &Cos{ client: cos.NewClient(&cos.BaseURL{BucketURL: bUrl}, &http.Client{ Transport: &cos.AuthorizationTransport{ SecretID: bConf.SecretId, SecretKey: bConf.SecretKey, }, }), baseUrl: baseUrl, bucket: bConf.Bucket, appId: a[len(a)-1], region: bConf.Region, }, nil } type CosToken struct { sts.Credentials Bucket string Region string } var defaultAllowPath = "/" func (c *Cos) GetToken(allowPath *string) (*CosToken, error) { if allowPath == nil { allowPath = &defaultAllowPath } stsCli := sts.NewClient(conf.Cos[c.bucket].SecretId, conf.Cos[c.bucket].SecretKey, nil) crt, err := stsCli.GetCredential(&sts.CredentialOptions{ DurationSeconds: 3600, Region: c.region, Policy: &sts.CredentialPolicy{ Statement: []sts.CredentialPolicyStatement{{ Action: []string{"name/cos:PostObject", "name/cos:PutObject", "name/cos:InitiateMultipartUpload", "name/cos:ListMultipartUploads", "name/cos:ListParts", "name/cos:UploadPart", "name/cos:CompleteMultipartUpload"}, Effect: "allow", Resource: []string{"qcs::cos:" + c.region + ":uid/" + c.appId + ":" + c.bucket + *allowPath + "*"}, }}, }, }) if err == nil { return &CosToken{ Credentials: *crt.Credentials, Bucket: c.bucket, Region: c.region, }, nil } return nil, err } func (c *Cos) Put(name string, data any) (string, error) { var err error if v, ok := data.(string); ok { if u.FileExists(v) { buf := u.ReadFileBytesN(v) _, err = c.client.Object.Put(context.Background(), name, bytes.NewReader(buf), nil) } else { _, err = c.client.Object.Put(context.Background(), name, strings.NewReader(v), nil) } } else if v, ok := data.([]byte); ok { _, err = c.client.Object.Put(context.Background(), name, bytes.NewReader(v), nil) } else { _, err = c.client.Object.Put(context.Background(), name, strings.NewReader(u.Json(data)), nil) } if err == nil { return c.baseUrl + "/" + name, nil } else { return "", err } } func (c *Cos) Get(name string) ([]byte, error) { r, err := c.client.Object.Get(context.Background(), name, nil) if err != nil { return nil, err } defer r.Body.Close() return io.ReadAll(r.Body) } func (c *Cos) MakeUrl(name string, expires *int64) (string, error) { expiresTime := time.Second * 300 if expires != nil && *expires > 0 { expiresTime = time.Millisecond * time.Duration(*expires) } r, err := c.client.Object.GetPresignedURL2(context.Background(), "GET", name, expiresTime, nil) if err != nil { return "", err } return r.String(), nil } func (c *Cos) Delete(name string) error { _, err := c.client.Object.Delete(context.Background(), name) return err } func (c *Cos) Head(name string) (*http.Header, error) { r, err := c.client.Object.Head(context.Background(), name, nil) if err != nil { return nil, err } return &r.Header, nil }