♻️ refactored thumbnail storage strategy
This commit is contained in:
@@ -24,7 +24,7 @@ func NewDownloadAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Dow
|
||||
}
|
||||
|
||||
func (l *DownloadAlbumLogic) DownloadAlbum(req *types.DownloadAlbumRequest) (resp string, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// todo: download album logic
|
||||
|
||||
return
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gen"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
@@ -63,6 +64,14 @@ func (l *GetAlbumDetailLogic) GetAlbumDetail(req *types.AlbumDetailListRequest)
|
||||
// 数据库查询文件信息列表
|
||||
var storageInfoQuery query.IScaStorageInfoDo
|
||||
var storageInfoList []types.FileInfoResult
|
||||
var queryCondition []gen.Condition
|
||||
queryCondition = append(queryCondition, storageInfo.UserID.Eq(uid))
|
||||
queryCondition = append(queryCondition, storageInfo.AlbumID.Eq(req.ID))
|
||||
// 类型筛选 1 是分享类型
|
||||
if req.Type != constant.AlbumTypeShared {
|
||||
queryCondition = append(queryCondition, storageInfo.Provider.Eq(req.Provider))
|
||||
queryCondition = append(queryCondition, storageInfo.Bucket.Eq(req.Bucket))
|
||||
}
|
||||
|
||||
storageInfoQuery = storageInfo.Select(
|
||||
storageInfo.ID,
|
||||
@@ -74,11 +83,7 @@ func (l *GetAlbumDetailLogic) GetAlbumDetail(req *types.AlbumDetailListRequest)
|
||||
storageThumb.ThumbH,
|
||||
storageThumb.ThumbSize).
|
||||
LeftJoin(storageThumb, storageInfo.ID.EqCol(storageThumb.InfoID)).
|
||||
Where(
|
||||
storageInfo.UserID.Eq(uid),
|
||||
storageInfo.Provider.Eq(req.Provider),
|
||||
storageInfo.Bucket.Eq(req.Bucket),
|
||||
storageInfo.AlbumID.Eq(req.ID)).
|
||||
Where(queryCondition...).
|
||||
Order(storageInfo.CreatedAt.Desc())
|
||||
err = storageInfoQuery.Scan(&storageInfoList)
|
||||
if err != nil {
|
||||
@@ -103,24 +108,41 @@ func (l *GetAlbumDetailLogic) GetAlbumDetail(req *types.AlbumDetailListRequest)
|
||||
// 按日期进行分组
|
||||
var wg sync.WaitGroup
|
||||
groupedImages := sync.Map{}
|
||||
|
||||
reqParams := make(url.Values)
|
||||
for _, dbFileInfo := range storageInfoList {
|
||||
wg.Add(1)
|
||||
go func(dbFileInfo *types.FileInfoResult) {
|
||||
defer wg.Done()
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
|
||||
var thumbnailUrl string
|
||||
var originalUrl string
|
||||
|
||||
if req.Type == constant.AlbumTypeShared {
|
||||
minioOriginalUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ShareImagesBucketName, dbFileInfo.Path, 30*time.Minute, reqParams)
|
||||
originalUrl = minioOriginalUrl.String()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
minioThumbnailUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, 30*time.Minute, reqParams)
|
||||
thumbnailUrl = minioThumbnailUrl.String()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
thumbnailUrl, err = service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
originalUrl, err = service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 Load 或 Store 确保原子操作
|
||||
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||
images := value.([]types.ImageMeta)
|
||||
@@ -128,8 +150,8 @@ func (l *GetAlbumDetailLogic) GetAlbumDetail(req *types.AlbumDetailListRequest)
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
URL: url,
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: originalUrl,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
CreatedAt: dbFileInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
|
@@ -39,10 +39,10 @@ func (l *GetAlbumListLogic) GetAlbumList(req *types.AlbumListRequest) (resp *typ
|
||||
orderConditions = append(orderConditions, storageAlbum.AlbumName.Desc())
|
||||
}
|
||||
var typeConditions []gen.Condition
|
||||
typeConditions = append(typeConditions, storageAlbum.UserID.Eq(uid))
|
||||
if req.Type != -1 {
|
||||
// 获取全部相册
|
||||
typeConditions = append(typeConditions, storageAlbum.AlbumType.Eq(req.Type))
|
||||
typeConditions = append(typeConditions, storageAlbum.UserID.Eq(uid))
|
||||
}
|
||||
albums, err := storageAlbum.Where(
|
||||
typeConditions...).
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
@@ -108,13 +107,12 @@ func (l *GetDeleteRecordLogic) GetDeleteRecord(req *types.QueryDeleteRecordReque
|
||||
defer wg.Done()
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
@@ -126,7 +124,7 @@ func (l *GetDeleteRecordLogic) GetDeleteRecord(req *types.QueryDeleteRecordReque
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
@@ -106,13 +105,13 @@ func (l *GetFaceDetailListLogic) GetFaceDetailList(req *types.FaceDetailListRequ
|
||||
defer wg.Done()
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
@@ -125,7 +124,7 @@ func (l *GetFaceDetailListLogic) GetFaceDetailList(req *types.FaceDetailListRequ
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
|
@@ -11,7 +11,6 @@ import (
|
||||
"golang.org/x/sync/semaphore"
|
||||
"gorm.io/gen"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
@@ -135,13 +134,12 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
||||
defer sem.Release(1)
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
@@ -153,7 +151,7 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/query"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
@@ -112,13 +111,12 @@ func (l *QueryLocationDetailListLogic) QueryLocationDetailList(req *types.Locati
|
||||
defer wg.Done()
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
@@ -130,7 +128,7 @@ func (l *QueryLocationDetailListLogic) QueryLocationDetailList(req *types.Locati
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
|
@@ -2,12 +2,16 @@ package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
storageConfig "schisandra-album-cloud-microservices/common/storage/config"
|
||||
"time"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
@@ -54,6 +58,18 @@ func (l *QueryLocationImageListLogic) QueryLocationImageList(req *types.Location
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 加载用户oss配置信息
|
||||
cacheOssConfigKey := constant.UserOssConfigPrefix + uid + ":" + req.Provider
|
||||
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, uid, req.Provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
|
||||
if err != nil {
|
||||
return nil, errors.New("get storage failed")
|
||||
}
|
||||
|
||||
locationMap := make(map[string][]types.LocationMeta)
|
||||
|
||||
for _, loc := range locations {
|
||||
@@ -68,16 +84,16 @@ func (l *QueryLocationImageListLogic) QueryLocationImageList(req *types.Location
|
||||
if city == "" {
|
||||
city = loc.Country
|
||||
}
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, loc.CoverImage, 15*time.Minute, reqParams)
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, loc.CoverImage, time.Minute*30)
|
||||
if err != nil {
|
||||
return nil, errors.New("get presigned url failed")
|
||||
logx.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
locationMeta := types.LocationMeta{
|
||||
ID: loc.ID,
|
||||
City: city,
|
||||
Total: loc.Total,
|
||||
CoverImage: presignedUrl.String(),
|
||||
CoverImage: thumbnailUrl,
|
||||
}
|
||||
locationMap[locationKey] = append(locationMap[locationKey], locationMeta)
|
||||
}
|
||||
@@ -93,3 +109,63 @@ func (l *QueryLocationImageListLogic) QueryLocationImageList(req *types.Location
|
||||
|
||||
return &types.LocationListResponse{Records: locationListData}, nil
|
||||
}
|
||||
|
||||
// 提取解密操作为函数
|
||||
func (l *QueryLocationImageListLogic) decryptConfig(config *model.ScaStorageConfig) (*storageConfig.StorageConfig, error) {
|
||||
accessKey, err := encrypt.Decrypt(config.AccessKey, l.svcCtx.Config.Encrypt.Key)
|
||||
if err != nil {
|
||||
return nil, errors.New("decrypt access key failed")
|
||||
}
|
||||
secretKey, err := encrypt.Decrypt(config.SecretKey, l.svcCtx.Config.Encrypt.Key)
|
||||
if err != nil {
|
||||
return nil, errors.New("decrypt secret key failed")
|
||||
}
|
||||
return &storageConfig.StorageConfig{
|
||||
Provider: config.Provider,
|
||||
Endpoint: config.Endpoint,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
BucketName: config.Bucket,
|
||||
Region: config.Region,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 从缓存或数据库中获取 OSS 配置
|
||||
func (l *QueryLocationImageListLogic) getOssConfigFromCacheOrDb(cacheKey, uid, provider string) (*storageConfig.StorageConfig, error) {
|
||||
result, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result()
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
return nil, errors.New("get oss config failed")
|
||||
}
|
||||
|
||||
var ossConfig *storageConfig.StorageConfig
|
||||
if result != "" {
|
||||
var redisOssConfig model.ScaStorageConfig
|
||||
if err = json.Unmarshal([]byte(result), &redisOssConfig); err != nil {
|
||||
return nil, errors.New("unmarshal oss config failed")
|
||||
}
|
||||
return l.decryptConfig(&redisOssConfig)
|
||||
}
|
||||
|
||||
// 缓存未命中,从数据库中加载
|
||||
scaOssConfig := l.svcCtx.DB.ScaStorageConfig
|
||||
dbOssConfig, err := scaOssConfig.Where(scaOssConfig.UserID.Eq(uid), scaOssConfig.Provider.Eq(provider)).First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 缓存数据库配置
|
||||
ossConfig, err = l.decryptConfig(dbOssConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
marshalData, err := json.Marshal(dbOssConfig)
|
||||
if err != nil {
|
||||
return nil, errors.New("marshal oss config failed")
|
||||
}
|
||||
err = l.svcCtx.RedisClient.Set(l.ctx, cacheKey, marshalData, 0).Err()
|
||||
if err != nil {
|
||||
return nil, errors.New("set oss config failed")
|
||||
}
|
||||
|
||||
return ossConfig, nil
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
@@ -119,13 +118,12 @@ func (l *QueryRecentImageListLogic) QueryRecentImageList(req *types.RecentListRe
|
||||
defer sem.Release(1)
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
@@ -137,7 +135,7 @@ func (l *QueryRecentImageListLogic) QueryRecentImageList(req *types.RecentListRe
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/query"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
@@ -112,13 +111,12 @@ func (l *QueryThingDetailListLogic) QueryThingDetailList(req *types.ThingDetailL
|
||||
defer wg.Done()
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, dbFileInfo.ThumbPath, time.Hour*24*7, reqParams)
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
@@ -130,7 +128,7 @@ func (l *QueryThingDetailListLogic) QueryThingDetailList(req *types.ThingDetailL
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
Thumbnail: thumbnailUrl,
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"net/url"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
@@ -65,16 +64,16 @@ func (l *QueryThingImageListLogic) QueryThingImageList(req *types.ThingListReque
|
||||
}
|
||||
|
||||
// 加载用户oss配置信息
|
||||
//cacheOssConfigKey := constant.UserOssConfigPrefix + uid + ":" + req.Provider
|
||||
//ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, uid, req.Provider)
|
||||
//if err != nil {
|
||||
// return nil, err
|
||||
//}
|
||||
//
|
||||
//service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
|
||||
//if err != nil {
|
||||
// return nil, errors.New("get storage failed")
|
||||
//}
|
||||
cacheOssConfigKey := constant.UserOssConfigPrefix + uid + ":" + req.Provider
|
||||
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, uid, req.Provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
|
||||
if err != nil {
|
||||
return nil, errors.New("get storage failed")
|
||||
}
|
||||
|
||||
categoryMap := sync.Map{}
|
||||
tagCountMap := sync.Map{}
|
||||
@@ -97,11 +96,12 @@ func (l *QueryThingImageListLogic) QueryThingImageList(req *types.ThingListReque
|
||||
// 为每个 Tag 存储封面图片路径
|
||||
if _, exists := tagCoverMap.Load(tagKey); !exists {
|
||||
// 使用服务生成预签名 URL
|
||||
reqParams := make(url.Values)
|
||||
presignedUrl, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, info.ThumbPath, time.Hour*24*7, reqParams)
|
||||
if err == nil {
|
||||
tagCoverMap.Store(tagKey, presignedUrl.String())
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, info.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return nil, errors.New("get presigned url failed")
|
||||
}
|
||||
tagCoverMap.Store(tagKey, thumbnailUrl)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,7 @@ func (l *SetStorageConfigLogic) SetStorageConfig(req *types.StorageConfigRequest
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
Region: req.Region,
|
||||
Capacity: req.Capacity,
|
||||
}
|
||||
err = l.svcCtx.DB.ScaStorageConfig.Create(ossConfig)
|
||||
if err != nil {
|
||||
|
@@ -87,8 +87,6 @@ func (l *ShareAlbumLogic) ShareAlbum(req *types.ShareAlbumRequest) (resp string,
|
||||
AccessPassword: req.AccessPassword,
|
||||
VisitLimit: req.AccessLimit,
|
||||
ImageCount: imageCount,
|
||||
Provider: req.Provider,
|
||||
Bucket: req.Bucket,
|
||||
Status: 0,
|
||||
}
|
||||
err = storageShare.Create(storageShareInfo)
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ccpwcn/kgo"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -79,9 +78,9 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
|
||||
// 使用 `errgroup.Group` 处理并发任务
|
||||
var (
|
||||
faceId int64
|
||||
filePath string
|
||||
minioFilePath string
|
||||
faceId int64
|
||||
filePath string
|
||||
thumbPath string
|
||||
)
|
||||
g, ctx := errgroup.WithContext(context.Background())
|
||||
// 创建信号量,限制最大并发上传数(比如最多同时 5 个任务)
|
||||
@@ -119,26 +118,12 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
Closer: io.NopCloser(nil),
|
||||
}
|
||||
|
||||
fileUrl, err := l.uploadFileToOSS(uid, header, fileReader, result)
|
||||
fileUrl, thumbUrl, err := l.uploadFileToOSS(uid, header, fileReader, thumbnail, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filePath = fileUrl
|
||||
return nil
|
||||
})
|
||||
|
||||
// 上传缩略图到 MinIO
|
||||
g.Go(func() error {
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
|
||||
path, err := l.uploadFileToMinio(uid, header, thumbnail, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
minioFilePath = path
|
||||
thumbPath = thumbUrl
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -149,11 +134,11 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
|
||||
fileUploadMessage := &types.FileUploadMessage{
|
||||
UID: uid,
|
||||
Data: result,
|
||||
Result: result,
|
||||
FaceID: faceId,
|
||||
FileHeader: header,
|
||||
FilePath: filePath,
|
||||
ThumbPath: minioFilePath,
|
||||
ThumbPath: thumbPath,
|
||||
}
|
||||
// 转换为 JSON
|
||||
messageData, err := json.Marshal(fileUploadMessage)
|
||||
@@ -205,19 +190,19 @@ func (l *UploadFileLogic) parseImageInfoResult(r *http.Request) (types.File, err
|
||||
}
|
||||
|
||||
// 上传文件到 OSS
|
||||
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, error) {
|
||||
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file multipart.File, thumbnail multipart.File, result types.File) (string, string, error) {
|
||||
cacheKey := constant.UserOssConfigPrefix + uid + ":" + result.Provider
|
||||
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheKey, uid, result.Provider)
|
||||
if err != nil {
|
||||
return "", errors.New("get oss config failed")
|
||||
return "", "", errors.New("get oss config failed")
|
||||
}
|
||||
service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
|
||||
if err != nil {
|
||||
return "", errors.New("get storage failed")
|
||||
return "", "", errors.New("get storage failed")
|
||||
}
|
||||
|
||||
objectKey := path.Join(
|
||||
"image_space",
|
||||
constant.ImageSpace,
|
||||
uid,
|
||||
time.Now().Format("2006/01"), // 按年/月划分目录
|
||||
l.classifyFile(result.FileType, result.IsScreenshot),
|
||||
@@ -228,52 +213,62 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
"Content-Type": header.Header.Get("Content-Type"),
|
||||
})
|
||||
if err != nil {
|
||||
return "", errors.New("upload file failed")
|
||||
return "", "", errors.New("upload file failed")
|
||||
}
|
||||
//url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, objectKey, time.Hour*24*7)
|
||||
//if err != nil {
|
||||
// return "", "", errors.New("presigned url failed")
|
||||
//}
|
||||
return objectKey, nil
|
||||
}
|
||||
|
||||
func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, error) {
|
||||
objectKey := path.Join(
|
||||
// 上传缩略图
|
||||
thumbObjectKey := path.Join(
|
||||
constant.ThumbnailSpace,
|
||||
uid,
|
||||
time.Now().Format("2006/01"), // 按年/月划分目录
|
||||
l.classifyFile(result.FileType, result.IsScreenshot),
|
||||
fmt.Sprintf("%s_%s%s", strings.TrimSuffix(header.Filename, filepath.Ext(header.Filename)), kgo.SimpleUuid(), filepath.Ext(header.Filename)),
|
||||
)
|
||||
exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.ThumbnailBucketName)
|
||||
if err != nil || !exists {
|
||||
err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.ThumbnailBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
|
||||
if err != nil {
|
||||
logx.Errorf("Failed to create MinIO bucket: %v", err)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
// 上传到MinIO
|
||||
_, err = l.svcCtx.MinioClient.PutObject(
|
||||
l.ctx,
|
||||
constant.ThumbnailBucketName,
|
||||
objectKey,
|
||||
file,
|
||||
int64(result.ThumbSize),
|
||||
minio.PutObjectOptions{
|
||||
ContentType: result.FileType,
|
||||
},
|
||||
)
|
||||
_, err = service.UploadFileSimple(l.ctx, ossConfig.BucketName, thumbObjectKey, thumbnail, map[string]string{
|
||||
"Content-Type": header.Header.Get("Content-Type"),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", "", errors.New("upload thumbnail file failed")
|
||||
}
|
||||
//reqParams := make(url.Values)
|
||||
//presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, objectKey, time.Hour*24*7, reqParams)
|
||||
//if err != nil {
|
||||
// return "", "", err
|
||||
//}
|
||||
return objectKey, nil
|
||||
return objectKey, thumbObjectKey, nil
|
||||
}
|
||||
|
||||
//func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, error) {
|
||||
// objectKey := path.Join(
|
||||
// uid,
|
||||
// time.Now().Format("2006/01"), // 按年/月划分目录
|
||||
// l.classifyFile(result.FileType, result.IsScreenshot),
|
||||
// fmt.Sprintf("%s_%s%s", strings.TrimSuffix(header.Filename, filepath.Ext(header.Filename)), kgo.SimpleUuid(), filepath.Ext(header.Filename)),
|
||||
// )
|
||||
// exists, err := l.svcCtx.MinioClient.BucketExists(l.ctx, constant.ThumbnailBucketName)
|
||||
// if err != nil || !exists {
|
||||
// err = l.svcCtx.MinioClient.MakeBucket(l.ctx, constant.ThumbnailBucketName, minio.MakeBucketOptions{Region: "us-east-1", ObjectLocking: true})
|
||||
// if err != nil {
|
||||
// logx.Errorf("Failed to create MinIO bucket: %v", err)
|
||||
// return "", err
|
||||
// }
|
||||
// }
|
||||
// // 上传到MinIO
|
||||
// _, err = l.svcCtx.MinioClient.PutObject(
|
||||
// l.ctx,
|
||||
// constant.ThumbnailBucketName,
|
||||
// objectKey,
|
||||
// file,
|
||||
// int64(result.ThumbSize),
|
||||
// minio.PutObjectOptions{
|
||||
// ContentType: result.FileType,
|
||||
// },
|
||||
// )
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// //reqParams := make(url.Values)
|
||||
// //presignedURL, err := l.svcCtx.MinioClient.PresignedGetObject(l.ctx, constant.ThumbnailBucketName, objectKey, time.Hour*24*7, reqParams)
|
||||
// //if err != nil {
|
||||
// // return "", "", err
|
||||
// //}
|
||||
// return objectKey, nil
|
||||
//}
|
||||
|
||||
// 提取解密操作为函数
|
||||
func (l *UploadFileLogic) decryptConfig(dbConfig *model.ScaStorageConfig) (*config.StorageConfig, error) {
|
||||
accessKey, err := encrypt.Decrypt(dbConfig.AccessKey, l.svcCtx.Config.Encrypt.Key)
|
||||
@@ -352,14 +347,15 @@ func (l *UploadFileLogic) classifyFile(mimeType string, isScreenshot bool) strin
|
||||
"video/x-matroska": "video",
|
||||
}
|
||||
|
||||
// 如果isScreenshot为true,则返回"screenshot"
|
||||
if isScreenshot {
|
||||
return "screenshot"
|
||||
}
|
||||
|
||||
// 根据MIME类型从map中获取分类
|
||||
if classification, exists := typeMap[mimeType]; exists {
|
||||
return classification
|
||||
}
|
||||
|
||||
// 如果isScreenshot为true,则返回"screenshot"
|
||||
if isScreenshot {
|
||||
return "screenshot"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
Reference in New Issue
Block a user