2024-12-20 18:35:59 +08:00
|
|
|
package tencent
|
|
|
|
|
|
|
|
import (
|
2025-01-14 14:34:54 +08:00
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
2024-12-20 18:35:59 +08:00
|
|
|
"strings"
|
2025-01-14 14:34:54 +08:00
|
|
|
"time"
|
2024-12-20 18:35:59 +08:00
|
|
|
|
2025-01-14 14:34:54 +08:00
|
|
|
"github.com/ssgo/u"
|
|
|
|
"github.com/tencentyun/cos-go-sdk-v5"
|
2024-12-20 18:35:59 +08:00
|
|
|
sts "github.com/tencentyun/qcloud-cos-sts-sdk/go"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Cos struct {
|
2025-01-14 14:34:54 +08:00
|
|
|
client *cos.Client
|
|
|
|
baseUrl string
|
|
|
|
bucket string
|
|
|
|
appId string
|
|
|
|
region string
|
2024-12-20 18:35:59 +08:00
|
|
|
}
|
|
|
|
|
2025-01-14 14:34:54 +08:00
|
|
|
func GetCos(bucket string) (*Cos, error) {
|
2024-12-20 18:35:59 +08:00
|
|
|
bConf := conf.Cos[bucket]
|
2025-01-14 14:34:54 +08:00
|
|
|
if bConf == nil {
|
|
|
|
return nil, errors.New("bucket not found")
|
|
|
|
}
|
2024-12-20 18:35:59 +08:00
|
|
|
a := strings.Split(bConf.Bucket, "-")
|
2025-01-14 14:34:54 +08:00
|
|
|
baseUrl := "https://" + bConf.Bucket + ".cos." + bConf.Region + ".myqcloud.com"
|
|
|
|
bUrl, _ := url.Parse(baseUrl)
|
2024-12-20 18:35:59 +08:00
|
|
|
return &Cos{
|
2025-01-14 14:34:54 +08:00
|
|
|
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
|
2024-12-20 18:35:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type CosToken struct {
|
|
|
|
sts.Credentials
|
|
|
|
Bucket string
|
|
|
|
Region string
|
|
|
|
}
|
|
|
|
|
|
|
|
var defaultAllowPath = "/"
|
|
|
|
|
|
|
|
func (c *Cos) GetToken(allowPath *string) (*CosToken, error) {
|
|
|
|
if allowPath == nil {
|
|
|
|
allowPath = &defaultAllowPath
|
|
|
|
}
|
2025-01-14 14:34:54 +08:00
|
|
|
stsCli := sts.NewClient(conf.Cos[c.bucket].SecretId, conf.Cos[c.bucket].SecretKey, nil)
|
|
|
|
crt, err := stsCli.GetCredential(&sts.CredentialOptions{
|
2024-12-20 18:35:59 +08:00
|
|
|
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
|
|
|
|
}
|
2025-01-14 14:34:54 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|