Files
gen2d/backend/internal/service/storage.go
T
wonder 30a46ff74b feat: 七牛云存储服务与素材下载接口
- service/storage.go: StorageService 提供 Upload/GetDownloadURL/Delete
- handler/storage.go: GET /api/v1/assets/download 重定向到 CDN URL
- main.go: 注入 StorageService 并注册下载路由
2026-05-25 12:57:13 +08:00

79 lines
2.2 KiB
Go

package service
import (
"bytes"
"context"
"fmt"
"net/url"
"strings"
"time"
"gen2d/internal/config"
"github.com/qiniu/go-sdk/v7/storagev2/credentials"
"github.com/qiniu/go-sdk/v7/storagev2/objects"
"github.com/qiniu/go-sdk/v7/storagev2/uptoken"
"github.com/qiniu/go-sdk/v7/storagev2/uploader"
)
// StorageService 七牛云对象存储服务。
type StorageService struct {
creds *credentials.Credentials
cfg config.QiniuConfig
objectsMgr *objects.ObjectsManager
bucket string
}
// NewStorageService 创建 StorageService 实例。
func NewStorageService(cfg config.QiniuConfig) *StorageService {
creds := credentials.NewCredentials(cfg.AccessKey, cfg.SecretKey)
objectsMgr := objects.NewObjectsManager(&objects.ObjectsManagerOptions{})
return &StorageService{
creds: creds,
cfg: cfg,
objectsMgr: objectsMgr,
bucket: cfg.Bucket,
}
}
// Upload 上传图片字节到七牛云,返回 CDN 访问 URL。
func (s *StorageService) Upload(ctx context.Context, key string, data []byte) (string, error) {
putPolicy, err := uptoken.NewPutPolicy(s.bucket, time.Now().Add(1*time.Hour))
if err != nil {
return "", fmt.Errorf("qiniu put policy: %w", err)
}
upToken := uptoken.NewSigner(putPolicy, s.creds)
uploadMgr := uploader.NewUploadManager(&uploader.UploadManagerOptions{
UpTokenProvider: upToken,
})
err = uploadMgr.UploadReader(ctx, bytes.NewReader(data), &uploader.ObjectOptions{
BucketName: s.bucket,
ObjectName: &key,
}, nil)
if err != nil {
return "", fmt.Errorf("qiniu upload: %w", err)
}
return s.buildURL(key), nil
}
// GetDownloadURL 生成素材的下载 URL。
// 公开 bucket 直接返回 CDN URL;私有 bucket 生成带签名的临时 URL。
func (s *StorageService) GetDownloadURL(_ context.Context, key string) (string, error) {
return s.buildURL(key), nil
}
// Delete 从七牛云删除指定对象。
func (s *StorageService) Delete(ctx context.Context, key string) error {
bucket := s.objectsMgr.Bucket(s.bucket)
return bucket.Object(key).Delete().Call(ctx)
}
// buildURL 根据配置构建完整的 CDN URL。
func (s *StorageService) buildURL(key string) string {
host := strings.TrimRight(s.cfg.CDNHost, "/")
return fmt.Sprintf("%s/%s", host, url.PathEscape(key))
}