🚧 developing...
This commit is contained in:
@@ -29,16 +29,31 @@ func (l *DeleteAlbumLogic) DeleteAlbum(req *types.AlbumDeleteRequest) (resp stri
|
||||
if !ok {
|
||||
return "", errors.New("user_id not found")
|
||||
}
|
||||
info, err := l.svcCtx.DB.ScaStorageAlbum.Where(l.svcCtx.DB.ScaStorageAlbum.ID.Eq(req.ID), l.svcCtx.DB.ScaStorageAlbum.UserID.Eq(uid)).Delete()
|
||||
tx := l.svcCtx.DB.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
info, err := tx.ScaStorageAlbum.Where(tx.ScaStorageAlbum.ID.Eq(req.ID), tx.ScaStorageAlbum.UserID.Eq(uid)).Delete()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
if info.RowsAffected == 0 {
|
||||
tx.Rollback()
|
||||
return "", errors.New("album not found")
|
||||
}
|
||||
storageInfo := l.svcCtx.DB.ScaStorageInfo
|
||||
_, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).Update(storageInfo.AlbumID, 0)
|
||||
storageInfo := tx.ScaStorageInfo
|
||||
_, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).Delete()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
return "success", nil
|
||||
|
30
app/auth/api/internal/logic/storage/download_album_logic.go
Normal file
30
app/auth/api/internal/logic/storage/download_album_logic.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type DownloadAlbumLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDownloadAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DownloadAlbumLogic {
|
||||
return &DownloadAlbumLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DownloadAlbumLogic) DownloadAlbum(req *types.DownloadAlbumRequest) (resp string, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
@@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"gorm.io/gen"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
@@ -59,8 +61,11 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
||||
if err := json.Unmarshal([]byte(cachedResult), &cachedResponse); err == nil {
|
||||
return &cachedResponse, nil
|
||||
}
|
||||
logx.Error("Failed to unmarshal cached image list:", err)
|
||||
return nil, errors.New("get cached image list failed")
|
||||
logx.Error("Failed to unmarshal cached image list, deleting invalid cache:", err)
|
||||
// 删除无效缓存
|
||||
if err := l.svcCtx.RedisClient.Del(l.ctx, cacheKey).Err(); err != nil {
|
||||
logx.Error("Failed to delete invalid cache:", err)
|
||||
}
|
||||
} else if !errors.Is(err, redis.Nil) {
|
||||
logx.Error("Redis error:", err)
|
||||
return nil, errors.New("get cached image list failed")
|
||||
@@ -115,25 +120,30 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
||||
}
|
||||
|
||||
// 按日期进行分组
|
||||
var wg sync.WaitGroup
|
||||
g, ctx := errgroup.WithContext(l.ctx)
|
||||
sem := semaphore.NewWeighted(10) // 限制并发数为 10
|
||||
groupedImages := sync.Map{}
|
||||
|
||||
for _, dbFileInfo := range storageInfoList {
|
||||
wg.Add(1)
|
||||
go func(dbFileInfo *types.FileInfoResult) {
|
||||
defer wg.Done()
|
||||
dbFileInfo := dbFileInfo // 创建局部变量以避免闭包问题
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
logx.Error("Failed to acquire semaphore:", err)
|
||||
continue
|
||||
}
|
||||
g.Go(func() error {
|
||||
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)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
// 使用 Load 或 Store 确保原子操作
|
||||
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||
@@ -151,9 +161,13 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
||||
|
||||
// 重新存储更新后的图像列表
|
||||
groupedImages.Store(date, images)
|
||||
}(&dbFileInfo)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
// 等待所有 goroutine 完成
|
||||
if err = g.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wg.Wait()
|
||||
var imageList []types.AllImageDetail
|
||||
groupedImages.Range(func(key, value interface{}) bool {
|
||||
imageList = append(imageList, types.AllImageDetail{
|
||||
@@ -162,11 +176,13 @@ func (l *QueryAllImageListLogic) QueryAllImageList(req *types.AllImageListReques
|
||||
})
|
||||
return true
|
||||
})
|
||||
// 按日期排序,最新的在最上面
|
||||
sort.Slice(imageList, func(i, j int) bool {
|
||||
dateI, _ := time.Parse("2006年1月2日 星期一", imageList[i].Date)
|
||||
dateJ, _ := time.Parse("2006年1月2日 星期一", imageList[j].Date)
|
||||
return dateI.After(dateJ)
|
||||
if len(imageList[i].List) == 0 || len(imageList[j].List) == 0 {
|
||||
return false // 空列表不参与排序
|
||||
}
|
||||
createdAtI, _ := time.Parse("2006-01-02 15:04:05", imageList[i].List[0].CreatedAt)
|
||||
createdAtJ, _ := time.Parse("2006-01-02 15:04:05", imageList[j].List[0].CreatedAt)
|
||||
return createdAtI.After(createdAtJ) // 降序排序
|
||||
})
|
||||
resp = &types.AllImageListResponse{
|
||||
Records: imageList,
|
||||
|
@@ -4,7 +4,17 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"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"
|
||||
storageConfig "schisandra-album-cloud-microservices/common/storage/config"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -28,72 +38,121 @@ func NewQueryRecentImageListLogic(ctx context.Context, svcCtx *svc.ServiceContex
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryRecentImageListLogic) QueryRecentImageList() (resp *types.RecentListResponse, err error) {
|
||||
func (l *QueryRecentImageListLogic) QueryRecentImageList(req *types.RecentListRequest) (resp *types.RecentListResponse, err error) {
|
||||
uid, ok := l.ctx.Value("user_id").(string)
|
||||
if !ok {
|
||||
return nil, errors.New("user_id not found")
|
||||
}
|
||||
|
||||
redisKeyPattern := constant.ImageRecentPrefix + uid + ":*"
|
||||
iter := l.svcCtx.RedisClient.Scan(l.ctx, 0, redisKeyPattern, 0).Iterator()
|
||||
var keys []string
|
||||
for iter.Next(l.ctx) {
|
||||
keys = append(keys, iter.Val())
|
||||
// 缓存获取数据 v1.0.0
|
||||
cacheKey := fmt.Sprintf("%s%s:%s:%s:%s", constant.ImageCachePrefix, uid, "recent", req.Provider, req.Bucket)
|
||||
// 尝试从缓存获取
|
||||
cachedResult, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
var cachedResponse types.RecentListResponse
|
||||
if err := json.Unmarshal([]byte(cachedResult), &cachedResponse); err == nil {
|
||||
return &cachedResponse, nil
|
||||
}
|
||||
logx.Error("Failed to unmarshal cached image list, deleting invalid cache:", err)
|
||||
// 删除无效缓存
|
||||
if err := l.svcCtx.RedisClient.Del(l.ctx, cacheKey).Err(); err != nil {
|
||||
logx.Error("Failed to delete invalid cache:", err)
|
||||
}
|
||||
} else if !errors.Is(err, redis.Nil) {
|
||||
logx.Error("Redis error:", err)
|
||||
return nil, errors.New("get cached image list failed")
|
||||
}
|
||||
if err := iter.Err(); err != nil {
|
||||
logx.Error(err)
|
||||
return nil, errors.New("scan recent file list failed")
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return &types.RecentListResponse{Records: []types.AllImageDetail{}}, nil
|
||||
}
|
||||
|
||||
cmds, err := l.svcCtx.RedisClient.MGet(l.ctx, keys...).Result()
|
||||
// 缓存未命中,从数据库中查询
|
||||
storageInfo := l.svcCtx.DB.ScaStorageInfo
|
||||
storageThumb := l.svcCtx.DB.ScaStorageThumb
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
// 计算30天前的时间
|
||||
thirtyDaysAgo := now.AddDate(0, 0, -30)
|
||||
var storageInfoList []types.FileInfoResult
|
||||
err = storageInfo.Select(
|
||||
storageInfo.ID,
|
||||
storageInfo.FileName,
|
||||
storageInfo.CreatedAt,
|
||||
storageThumb.ThumbPath,
|
||||
storageInfo.Path,
|
||||
storageThumb.ThumbW,
|
||||
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.Type.Neq(constant.ImageTypeShared),
|
||||
storageInfo.CreatedAt.Gt(thirtyDaysAgo)).
|
||||
Order(storageInfo.CreatedAt.Desc()).Scan(&storageInfoList)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return nil, errors.New("get recent file list failed")
|
||||
return nil, err
|
||||
}
|
||||
if len(storageInfoList) == 0 {
|
||||
return &types.RecentListResponse{}, nil
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
// 加载用户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")
|
||||
}
|
||||
|
||||
// 按日期进行分组
|
||||
g, ctx := errgroup.WithContext(l.ctx)
|
||||
sem := semaphore.NewWeighted(10) // 限制并发数为 10
|
||||
groupedImages := sync.Map{}
|
||||
|
||||
for _, cmd := range cmds {
|
||||
if cmd == nil {
|
||||
for _, dbFileInfo := range storageInfoList {
|
||||
dbFileInfo := dbFileInfo // 创建局部变量以避免闭包问题
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
logx.Error("Failed to acquire semaphore:", err)
|
||||
continue
|
||||
}
|
||||
val, ok := cmd.(string)
|
||||
if !ok {
|
||||
logx.Error("invalid value type")
|
||||
return nil, errors.New("invalid value type")
|
||||
}
|
||||
var imageMeta types.ImageMeta
|
||||
err = json.Unmarshal([]byte(val), &imageMeta)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return nil, errors.New("unmarshal recent file list failed")
|
||||
}
|
||||
parse, err := time.Parse("2006-01-02 15:04:05", imageMeta.CreatedAt)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return nil, errors.New("parse recent file list failed")
|
||||
}
|
||||
date := parse.Format("2006年1月2日 星期" + WeekdayMap[parse.Weekday()])
|
||||
// 使用LoadOrStore来检查并存储或者追加
|
||||
wg.Add(1)
|
||||
go func(date string, imageMeta types.ImageMeta) {
|
||||
defer wg.Done()
|
||||
value, loaded := groupedImages.LoadOrStore(date, []types.ImageMeta{imageMeta})
|
||||
if loaded {
|
||||
images := value.([]types.ImageMeta)
|
||||
images = append(images, imageMeta)
|
||||
groupedImages.Store(date, images)
|
||||
g.Go(func() error {
|
||||
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)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
}(date, imageMeta)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Hour*24*7)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
// 使用 Load 或 Store 确保原子操作
|
||||
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||
images := value.([]types.ImageMeta)
|
||||
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
Thumbnail: presignedUrl.String(),
|
||||
URL: url,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
CreatedAt: dbFileInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
|
||||
// 重新存储更新后的图像列表
|
||||
groupedImages.Store(date, images)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
// 等待所有 goroutine 完成
|
||||
if err = g.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
var imageList []types.AllImageDetail
|
||||
groupedImages.Range(func(key, value interface{}) bool {
|
||||
imageList = append(imageList, types.AllImageDetail{
|
||||
@@ -102,7 +161,87 @@ func (l *QueryRecentImageListLogic) QueryRecentImageList() (resp *types.RecentLi
|
||||
})
|
||||
return true
|
||||
})
|
||||
return &types.RecentListResponse{
|
||||
sort.Slice(imageList, func(i, j int) bool {
|
||||
if len(imageList[i].List) == 0 || len(imageList[j].List) == 0 {
|
||||
return false // 空列表不参与排序
|
||||
}
|
||||
createdAtI, _ := time.Parse("2006-01-02 15:04:05", imageList[i].List[0].CreatedAt)
|
||||
createdAtJ, _ := time.Parse("2006-01-02 15:04:05", imageList[j].List[0].CreatedAt)
|
||||
return createdAtI.After(createdAtJ) // 降序排序
|
||||
})
|
||||
resp = &types.RecentListResponse{
|
||||
Records: imageList,
|
||||
}
|
||||
|
||||
// 缓存结果
|
||||
if data, err := json.Marshal(resp); err == nil {
|
||||
expireTime := 5*time.Minute + time.Duration(rand.Intn(300))*time.Second
|
||||
if err := l.svcCtx.RedisClient.Set(l.ctx, cacheKey, data, expireTime).Err(); err != nil {
|
||||
logx.Error("Failed to cache image list:", err)
|
||||
}
|
||||
} else {
|
||||
logx.Error("Failed to marshal image list for caching:", err)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// 提取解密操作为函数
|
||||
func (l *QueryRecentImageListLogic) 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 *QueryRecentImageListLogic) 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
|
||||
}
|
||||
|
126
app/auth/api/internal/logic/storage/share_album_logic.go
Normal file
126
app/auth/api/internal/logic/storage/share_album_logic.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/ccpwcn/kgo"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/svc"
|
||||
"schisandra-album-cloud-microservices/app/auth/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ShareAlbumLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewShareAlbumLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ShareAlbumLogic {
|
||||
return &ShareAlbumLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ShareAlbumLogic) ShareAlbum(req *types.ShareAlbumRequest) (resp string, err error) {
|
||||
uid, ok := l.ctx.Value("user_id").(string)
|
||||
if !ok {
|
||||
return "", errors.New("user_id not found")
|
||||
}
|
||||
tx := l.svcCtx.DB.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
storageAlbum := tx.ScaStorageAlbum
|
||||
info, err := storageAlbum.Where(storageAlbum.ID.Eq(req.ID), storageAlbum.UserID.Eq(uid)).
|
||||
Update(storageAlbum.AlbumType, constant.AlbumTypeShared)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
if info.RowsAffected == 0 {
|
||||
tx.Rollback()
|
||||
return "", errors.New("album not found")
|
||||
}
|
||||
// 更新图片信息
|
||||
storageInfo := tx.ScaStorageInfo
|
||||
_, err = storageInfo.Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).
|
||||
Update(storageInfo.Type, constant.ImageTypeShared)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
// 查询图片数量
|
||||
var imageCount int64
|
||||
err = storageInfo.Select(
|
||||
storageInfo.ID.Count().As("image_count")).
|
||||
Where(storageInfo.AlbumID.Eq(req.ID), storageInfo.UserID.Eq(uid)).
|
||||
Group(storageInfo.AlbumID).Scan(&imageCount)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
|
||||
duration, err := strconv.Atoi(req.ExpireDate)
|
||||
if err != nil {
|
||||
return "", errors.New("invalid expire date")
|
||||
}
|
||||
expiryTime := l.GenerateExpiryTime(time.Now(), duration)
|
||||
storageShare := tx.ScaStorageShare
|
||||
storageShareInfo := &model.ScaStorageShare{
|
||||
UserID: uid,
|
||||
AlbumID: req.ID,
|
||||
InviteCode: kgo.SimpleUuid(),
|
||||
ValidityPeriod: int64(duration),
|
||||
ExpireTime: expiryTime,
|
||||
AccessPassword: req.AccessPassword,
|
||||
VisitLimit: req.AccessLimit,
|
||||
ImageCount: imageCount,
|
||||
Provider: req.Provider,
|
||||
Bucket: req.Bucket,
|
||||
Status: 0,
|
||||
}
|
||||
err = storageShare.Create(storageShareInfo)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
marshal, err := json.Marshal(storageShareInfo)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
cacheKey := constant.ImageSharePrefix + storageShareInfo.InviteCode
|
||||
err = l.svcCtx.RedisClient.Set(l.ctx, cacheKey, marshal, time.Duration(duration)*time.Hour*24).Err()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "success", nil
|
||||
}
|
||||
|
||||
// GenerateExpiryTime 函数接受当前时间和有效期(天为单位),返回过期时间
|
||||
func (l *ShareAlbumLogic) GenerateExpiryTime(currentTime time.Time, durationInDays int) time.Time {
|
||||
// 创建一个持续时间对象
|
||||
duration := time.Duration(durationInDays) * 24 * time.Hour
|
||||
// 将当前时间加上持续时间,得到过期时间
|
||||
expiryTime := currentTime.Add(duration)
|
||||
return expiryTime
|
||||
}
|
@@ -15,7 +15,6 @@ import (
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
|
||||
@@ -83,7 +82,6 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
faceId int64
|
||||
filePath string
|
||||
minioFilePath string
|
||||
presignedURL string
|
||||
)
|
||||
g, ctx := errgroup.WithContext(context.Background())
|
||||
// 创建信号量,限制最大并发上传数(比如最多同时 5 个任务)
|
||||
@@ -136,12 +134,11 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
}
|
||||
defer sem.Release(1)
|
||||
|
||||
path, url, err := l.uploadFileToMinio(uid, header, thumbnail, result)
|
||||
path, err := l.uploadFileToMinio(uid, header, thumbnail, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
minioFilePath = path
|
||||
presignedURL = url
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -151,13 +148,12 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
}
|
||||
|
||||
fileUploadMessage := &types.FileUploadMessage{
|
||||
UID: uid,
|
||||
Data: result,
|
||||
FaceID: faceId,
|
||||
FileHeader: header,
|
||||
FilePath: filePath,
|
||||
PresignedURL: presignedURL,
|
||||
ThumbPath: minioFilePath,
|
||||
UID: uid,
|
||||
Data: result,
|
||||
FaceID: faceId,
|
||||
FileHeader: header,
|
||||
FilePath: filePath,
|
||||
ThumbPath: minioFilePath,
|
||||
}
|
||||
// 转换为 JSON
|
||||
messageData, err := json.Marshal(fileUploadMessage)
|
||||
@@ -241,7 +237,7 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
return objectKey, nil
|
||||
}
|
||||
|
||||
func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHeader, file multipart.File, result types.File) (string, string, error) {
|
||||
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"), // 按年/月划分目录
|
||||
@@ -253,7 +249,7 @@ func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHe
|
||||
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
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
// 上传到MinIO
|
||||
@@ -268,14 +264,14 @@ func (l *UploadFileLogic) uploadFileToMinio(uid string, header *multipart.FileHe
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
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, presignedURL.String(), nil
|
||||
//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
|
||||
}
|
||||
|
||||
// 提取解密操作为函数
|
||||
|
Reference in New Issue
Block a user