package objectstorage import ( "bytes" "context" "strings" "img_infinite_canvas/internal/domain/design" "github.com/aliyun/aliyun-oss-go-sdk/oss" ) type AliyunOptions struct { Bucket string Endpoint string AccessKey string SecretKey string PublicBase string ExpiresIn int64 } type AliyunStorage struct { bucketName string publicBase string expiresIn int64 bucket *oss.Bucket } func NewAliyunStorage(ctx context.Context, opts AliyunOptions) (*AliyunStorage, error) { if err := ctx.Err(); err != nil { return nil, err } client, err := oss.New(opts.Endpoint, opts.AccessKey, opts.SecretKey) if err != nil { return nil, err } exists, err := client.IsBucketExist(opts.Bucket) if err != nil { return nil, err } if !exists { if err := client.CreateBucket(opts.Bucket); err != nil { return nil, err } } bucket, err := client.Bucket(opts.Bucket) if err != nil { return nil, err } if opts.ExpiresIn <= 0 { opts.ExpiresIn = 900 } return &AliyunStorage{ bucketName: opts.Bucket, publicBase: strings.TrimRight(opts.PublicBase, "/"), expiresIn: opts.ExpiresIn, bucket: bucket, }, nil } func (s *AliyunStorage) CreateUpload(ctx context.Context, req design.AssetUploadRequest) (design.AssetUpload, error) { if err := ctx.Err(); err != nil { return design.AssetUpload{}, err } objectKey := objectKey(req.FileName) signedURL, err := s.bucket.SignURL(objectKey, oss.HTTPPut, s.expiresIn, oss.ContentType(req.ContentType)) if err != nil { return design.AssetUpload{}, err } publicURL := signedURL if s.publicBase != "" { publicURL = publicObjectURL(s.publicBase, objectKey) } return design.AssetUpload{ Driver: "aliyun", Bucket: s.bucketName, ObjectKey: objectKey, UploadURL: signedURL, PublicURL: publicURL, Headers: map[string]string{ "Content-Type": req.ContentType, }, ExpiresIn: s.expiresIn, }, nil } func (s *AliyunStorage) PutObject(ctx context.Context, req design.AssetObjectRequest) (design.AssetObject, error) { if err := ctx.Err(); err != nil { return design.AssetObject{}, err } objectKey := objectKey(req.FileName) if err := s.bucket.PutObject(objectKey, bytes.NewReader(req.Data), oss.ContentType(req.ContentType)); err != nil { return design.AssetObject{}, err } publicURL := publicObjectURL(s.publicBase, objectKey) return design.AssetObject{ Driver: "aliyun", Bucket: s.bucketName, ObjectKey: objectKey, PublicURL: publicURL, }, nil } func (s *AliyunStorage) DeleteObject(ctx context.Context, publicURL string) error { if err := ctx.Err(); err != nil { return err } objectKey, ok := objectKeyFromPublicURL(s.publicBase, publicURL) if !ok { return nil } return s.bucket.DeleteObject(objectKey) }