🚧 improve image encryption and decryption
This commit is contained in:
@@ -35,13 +35,18 @@ func (l *GetCoordinateListLogic) GetCoordinateList() (resp *types.CoordinateList
|
||||
storageLocation.ID,
|
||||
storageLocation.Longitude,
|
||||
storageLocation.Latitude,
|
||||
storageLocation.Country,
|
||||
storageLocation.Province,
|
||||
storageLocation.City,
|
||||
storageInfo.ID.Count().As("image_count"),
|
||||
).Join(
|
||||
storageInfo,
|
||||
storageLocation.ID.EqCol(storageInfo.LocationID),
|
||||
).Where(storageLocation.UserID.Eq(uid),
|
||||
storageInfo.UserID.Eq(uid),
|
||||
).Scan(&records)
|
||||
).
|
||||
Group(storageLocation.ID).
|
||||
Scan(&records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -1,24 +1,20 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"gorm.io/gen"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"gorm.io/gorm"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/captcha/verify"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
storageConfig "schisandra-album-cloud-microservices/common/storage/config"
|
||||
"schisandra-album-cloud-microservices/common/utils"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -31,9 +27,8 @@ import (
|
||||
|
||||
type GetPrivateImageListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
RestyClient *resty.Client
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetPrivateImageListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPrivateImageListLogic {
|
||||
@@ -41,16 +36,6 @@ func NewGetPrivateImageListLogic(ctx context.Context, svcCtx *svc.ServiceContext
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
RestyClient: resty.New().
|
||||
SetTimeout(30 * time.Second). // 总超时时间
|
||||
SetRetryCount(3). // 重试次数
|
||||
SetRetryWaitTime(5 * time.Second). // 重试等待时间
|
||||
SetRetryMaxWaitTime(30 * time.Second). // 最大重试等待
|
||||
AddRetryCondition(func(r *resty.Response, err error) bool {
|
||||
return r.StatusCode() == http.StatusTooManyRequests ||
|
||||
err != nil ||
|
||||
r.StatusCode() >= 500
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +44,29 @@ func (l *GetPrivateImageListLogic) GetPrivateImageList(req *types.PrivateImageLi
|
||||
if !ok {
|
||||
return nil, errors.New("user_id not found")
|
||||
}
|
||||
captcha := verify.VerifyBasicTextCaptcha(req.Dots, req.Key, l.svcCtx.RedisClient, l.ctx)
|
||||
if !captcha {
|
||||
return nil, errors.New("验证错误")
|
||||
}
|
||||
if req.Password == "" {
|
||||
return nil, errors.New("密码不能为空")
|
||||
}
|
||||
authUser := l.svcCtx.DB.ScaAuthUser
|
||||
userInfo, err := authUser.
|
||||
Select(authUser.UID, authUser.Password).
|
||||
Where(authUser.UID.Eq(uid)).First()
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
if userInfo == nil {
|
||||
return nil, errors.New("密码错误")
|
||||
}
|
||||
if !utils.Verify(userInfo.Password, req.Password) {
|
||||
return nil, errors.New("密码错误")
|
||||
}
|
||||
|
||||
storageInfo := l.svcCtx.DB.ScaStorageInfo
|
||||
storageThumb := l.svcCtx.DB.ScaStorageThumb
|
||||
conditions := []gen.Condition{
|
||||
storageInfo.UserID.Eq(uid),
|
||||
storageInfo.Provider.Eq(req.Provider),
|
||||
@@ -74,10 +80,16 @@ func (l *GetPrivateImageListLogic) GetPrivateImageList(req *types.PrivateImageLi
|
||||
storageInfo.ID,
|
||||
storageInfo.FileName,
|
||||
storageInfo.CreatedAt,
|
||||
storageInfo.Path).
|
||||
storageThumb.ThumbPath,
|
||||
storageInfo.Path,
|
||||
storageThumb.ThumbW,
|
||||
storageThumb.ThumbH,
|
||||
storageThumb.ThumbSize,
|
||||
).
|
||||
LeftJoin(storageThumb, storageInfo.ID.EqCol(storageThumb.InfoID)).
|
||||
Where(conditions...).
|
||||
Order(storageInfo.CreatedAt.Desc()).Scan(&storageInfoList)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
if len(storageInfoList) == 0 {
|
||||
@@ -110,48 +122,15 @@ func (l *GetPrivateImageListLogic) GetPrivateImageList(req *types.PrivateImageLi
|
||||
g.Go(func() error {
|
||||
defer sem.Release(1)
|
||||
|
||||
// 生成单条缓存键(包含文件唯一标识)
|
||||
imageCacheKey := fmt.Sprintf("%s%s:%s:%s:%s:%v",
|
||||
constant.ImageCachePrefix,
|
||||
uid,
|
||||
"list",
|
||||
req.Provider,
|
||||
req.Bucket,
|
||||
dbFileInfo.ID)
|
||||
// 尝试获取单条缓存
|
||||
if cached, err := l.svcCtx.RedisClient.Get(l.ctx, imageCacheKey).Result(); err == nil {
|
||||
var meta types.ImageMeta
|
||||
if err := json.Unmarshal([]byte(cached), &meta); err == nil {
|
||||
parse, err := time.Parse("2006-01-02 15:04:05", meta.CreatedAt)
|
||||
if err == nil {
|
||||
logx.Error("Parse Time Error:", err)
|
||||
return nil
|
||||
}
|
||||
date := parse.Format("2006年1月2日 星期") + WeekdayMap[parse.Weekday()]
|
||||
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||
images := value.([]types.ImageMeta)
|
||||
images = append(images, meta)
|
||||
groupedImages.Store(date, images)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
weekday := WeekdayMap[dbFileInfo.CreatedAt.Weekday()]
|
||||
date := dbFileInfo.CreatedAt.Format("2006年1月2日 星期" + weekday)
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.Path, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
imageBytes, err := l.DownloadAndDecrypt(l.ctx, url, uid)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
imageData, err := l.svcCtx.XCipher.Decrypt(imageBytes, []byte(uid))
|
||||
|
||||
thumbnailUrl, err := service.PresignedURL(l.ctx, ossConfig.BucketName, dbFileInfo.ThumbPath, time.Minute*30)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 使用 Load 或 Store 确保原子操作
|
||||
value, _ := groupedImages.LoadOrStore(date, []types.ImageMeta{})
|
||||
images := value.([]types.ImageMeta)
|
||||
@@ -159,7 +138,7 @@ func (l *GetPrivateImageListLogic) GetPrivateImageList(req *types.PrivateImageLi
|
||||
images = append(images, types.ImageMeta{
|
||||
ID: dbFileInfo.ID,
|
||||
FileName: dbFileInfo.FileName,
|
||||
URL: base64.StdEncoding.EncodeToString(imageData),
|
||||
Thumbnail: thumbnailUrl,
|
||||
Width: dbFileInfo.ThumbW,
|
||||
Height: dbFileInfo.ThumbH,
|
||||
CreatedAt: dbFileInfo.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
@@ -167,14 +146,6 @@ func (l *GetPrivateImageListLogic) GetPrivateImageList(req *types.PrivateImageLi
|
||||
|
||||
// 重新存储更新后的图像列表
|
||||
groupedImages.Store(date, images)
|
||||
|
||||
// 缓存单条数据(24小时基础缓存 + 随机防雪崩)
|
||||
if data, err := json.Marshal(images); err == nil {
|
||||
expire := 24*time.Hour + time.Duration(rand.Intn(3600))*time.Second
|
||||
if err := l.svcCtx.RedisClient.Set(l.ctx, imageCacheKey, data, expire).Err(); err != nil {
|
||||
logx.Error("Failed to cache image meta:", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -263,27 +234,3 @@ func (l *GetPrivateImageListLogic) getOssConfigFromCacheOrDb(cacheKey, uid, prov
|
||||
|
||||
return ossConfig, nil
|
||||
}
|
||||
|
||||
func (l *GetPrivateImageListLogic) DownloadAndDecrypt(ctx context.Context, url string, uid string) ([]byte, error) {
|
||||
resp, err := l.RestyClient.R().
|
||||
SetContext(ctx).
|
||||
SetDoNotParseResponse(true). // 保持原始响应流
|
||||
Get(url)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
defer resp.RawBody().Close()
|
||||
|
||||
if resp.StatusCode() != http.StatusOK {
|
||||
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode(), resp.Status())
|
||||
}
|
||||
|
||||
// 使用缓冲区分块读取
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err := io.Copy(buf, resp.RawBody()); err != nil {
|
||||
return nil, fmt.Errorf("read response body failed: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
@@ -0,0 +1,218 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"gorm.io/gorm"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
"schisandra-album-cloud-microservices/common/hybrid_encrypt"
|
||||
storageConfig "schisandra-album-cloud-microservices/common/storage/config"
|
||||
"schisandra-album-cloud-microservices/common/utils"
|
||||
"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 GetPrivateImageUrlLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
RestyClient *resty.Client
|
||||
}
|
||||
|
||||
func NewGetPrivateImageUrlLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPrivateImageUrlLogic {
|
||||
return &GetPrivateImageUrlLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
RestyClient: resty.New().
|
||||
SetTimeout(30 * time.Second). // 总超时时间
|
||||
SetRetryCount(3). // 重试次数
|
||||
SetRetryWaitTime(5 * time.Second). // 重试等待时间
|
||||
SetRetryMaxWaitTime(30 * time.Second). // 最大重试等待
|
||||
AddRetryCondition(func(r *resty.Response, err error) bool {
|
||||
return r.StatusCode() == http.StatusTooManyRequests ||
|
||||
err != nil ||
|
||||
r.StatusCode() >= 500
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// 修改函数签名和实现
|
||||
func (l *GetPrivateImageUrlLogic) GetPrivateImageUrl(req *types.SinglePrivateImageRequest) (string, error) {
|
||||
uid, ok := l.ctx.Value("user_id").(string)
|
||||
if !ok {
|
||||
return "", errors.New("user_id not found")
|
||||
}
|
||||
|
||||
// 构建缓存key
|
||||
cacheKey := fmt.Sprintf("%s%s:%s:%v", constant.ImageCachePrefix, uid, "encrypted", req.ID)
|
||||
|
||||
// 检查缓存
|
||||
if cachedData, err := l.svcCtx.RedisClient.Get(l.ctx, cacheKey).Result(); err == nil {
|
||||
return cachedData, nil
|
||||
}
|
||||
|
||||
storageInfo := l.svcCtx.DB.ScaStorageInfo
|
||||
authUser := l.svcCtx.DB.ScaAuthUser
|
||||
var result struct {
|
||||
ID int64 `json:"id"`
|
||||
Path string `json:"path"`
|
||||
Password string `json:"password"`
|
||||
FileType string `json:"file_type"`
|
||||
}
|
||||
err := storageInfo.
|
||||
Select(
|
||||
storageInfo.ID,
|
||||
storageInfo.Path,
|
||||
storageInfo.FileType,
|
||||
authUser.Password).
|
||||
LeftJoin(authUser, authUser.UID.EqCol(storageInfo.UserID)).
|
||||
Where(storageInfo.ID.Eq(req.ID), storageInfo.UserID.Eq(uid),
|
||||
storageInfo.IsEncrypted.Eq(constant.Encrypt), storageInfo.Provider.Eq(req.Provider),
|
||||
storageInfo.Bucket.Eq(req.Bucket), authUser.UID.Eq(uid)).
|
||||
Group(storageInfo.ID).Scan(&result)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return "", err
|
||||
}
|
||||
if result.ID == 0 {
|
||||
return "", errors.New("image not found")
|
||||
}
|
||||
verify := utils.Verify(result.Password, req.Password)
|
||||
if !verify {
|
||||
return "", errors.New("invalid password")
|
||||
}
|
||||
|
||||
// 加载用户oss配置信息
|
||||
cacheOssConfigKey := constant.UserOssConfigPrefix + uid + ":" + req.Provider
|
||||
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheOssConfigKey, uid, req.Provider)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
service, err := l.svcCtx.StorageManager.GetStorage(uid, ossConfig)
|
||||
if err != nil {
|
||||
return "", errors.New("get storage failed")
|
||||
}
|
||||
url, err := service.PresignedURL(l.ctx, ossConfig.BucketName, result.Path, time.Minute*15)
|
||||
if err != nil {
|
||||
logx.Error(err)
|
||||
return "", errors.New("get private image url failed")
|
||||
}
|
||||
|
||||
resp, err := l.RestyClient.R().
|
||||
SetContext(l.ctx).
|
||||
SetDoNotParseResponse(true). // 保持原始响应流
|
||||
Get(url)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("download private image failed: %w", err)
|
||||
}
|
||||
defer resp.RawBody().Close()
|
||||
|
||||
body, err := io.ReadAll(resp.RawBody())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
privateKeyPath := filepath.Join(dir, l.svcCtx.Config.Encrypt.PrivateKey)
|
||||
privateKey, err := os.ReadFile(privateKeyPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pem, err := hybrid_encrypt.ImportPrivateKeyPEM(privateKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
image, err := hybrid_encrypt.DecryptImage(pem, body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
base64Str := base64.StdEncoding.EncodeToString(image)
|
||||
|
||||
// 设置缓存,过期时间设为12小时
|
||||
err = l.svcCtx.RedisClient.Set(l.ctx, cacheKey, base64Str, 12*time.Hour).Err()
|
||||
if err != nil {
|
||||
logx.Errorf("cache private image failed: %v", err)
|
||||
}
|
||||
|
||||
return base64Str, nil
|
||||
}
|
||||
|
||||
// 提取解密操作为函数
|
||||
func (l *GetPrivateImageUrlLogic) 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 *GetPrivateImageUrlLogic) 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
|
||||
}
|
@@ -14,6 +14,7 @@ import (
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
"schisandra-album-cloud-microservices/app/auth/model/mysql/model"
|
||||
"schisandra-album-cloud-microservices/common/constant"
|
||||
"schisandra-album-cloud-microservices/common/encrypt"
|
||||
"schisandra-album-cloud-microservices/common/hybrid_encrypt"
|
||||
"schisandra-album-cloud-microservices/common/storage/config"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -50,13 +52,16 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 解析上传配置信息
|
||||
settingResult, err := l.parseUploadSettingResult(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 解析上传的文件
|
||||
file, header, err := l.getUploadedFile(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
@@ -76,12 +81,6 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 解析上传配置信息
|
||||
settingResult, err := l.parseUploadSettingResult(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 使用 `errgroup.Group` 处理并发任务
|
||||
var (
|
||||
faceId int64
|
||||
@@ -110,13 +109,25 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
var imageBytes []byte
|
||||
|
||||
var uploadReader io.Reader = bytes.NewReader(data)
|
||||
if settingResult.Encrypt {
|
||||
encryptedData, err := l.svcCtx.XCipher.Encrypt(data, []byte(uid))
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
imageBytes = encryptedData
|
||||
publicKeyPath := filepath.Join(dir, l.svcCtx.Config.Encrypt.PublicKey)
|
||||
publicKey, err := os.ReadFile(publicKeyPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pem, err := hybrid_encrypt.ImportPublicKeyPEM(publicKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
image, err := hybrid_encrypt.EncryptImage(pem, data)
|
||||
uploadReader = bytes.NewReader(image)
|
||||
}
|
||||
|
||||
// 上传文件到 OSS
|
||||
@@ -126,7 +137,7 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
|
||||
}
|
||||
defer sem.Release(1)
|
||||
|
||||
fileUrl, thumbUrl, err := l.uploadFileToOSS(uid, header, bytes.NewReader(imageBytes), thumbnail, result)
|
||||
fileUrl, thumbUrl, err := l.uploadFileToOSS(uid, header, uploadReader, thumbnail, result, settingResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -210,7 +221,7 @@ func (l *UploadFileLogic) parseUploadSettingResult(r *http.Request) (types.Uploa
|
||||
}
|
||||
|
||||
// 上传文件到 OSS
|
||||
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file io.Reader, thumbnail io.Reader, result types.File) (string, string, error) {
|
||||
func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHeader, file io.Reader, thumbnail io.Reader, result types.File, settingResult types.UploadSetting) (string, string, error) {
|
||||
cacheKey := constant.UserOssConfigPrefix + uid + ":" + result.Provider
|
||||
ossConfig, err := l.getOssConfigFromCacheOrDb(cacheKey, uid, result.Provider)
|
||||
if err != nil {
|
||||
@@ -220,7 +231,6 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
if err != nil {
|
||||
return "", "", errors.New("get storage failed")
|
||||
}
|
||||
|
||||
objectKey := path.Join(
|
||||
constant.ImageSpace,
|
||||
uid,
|
||||
@@ -228,6 +238,15 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
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)),
|
||||
)
|
||||
if settingResult.Encrypt {
|
||||
objectKey = path.Join(
|
||||
constant.ImageSpace,
|
||||
uid,
|
||||
time.Now().Format("2006/01"), // 按年/月划分目录
|
||||
"encrypted",
|
||||
fmt.Sprintf("%s_%s%s", strings.TrimSuffix(header.Filename, filepath.Ext(header.Filename)), kgo.SimpleUuid(), ".enc"),
|
||||
)
|
||||
}
|
||||
|
||||
_, err = service.UploadFileSimple(l.ctx, ossConfig.BucketName, objectKey, file, map[string]string{
|
||||
"Content-Type": header.Header.Get("Content-Type"),
|
||||
@@ -241,7 +260,7 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
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)),
|
||||
fmt.Sprintf("%s_%s", strings.TrimSuffix(header.Filename, filepath.Ext(header.Filename)), kgo.SimpleUuid()),
|
||||
)
|
||||
_, err = service.UploadFileSimple(l.ctx, ossConfig.BucketName, thumbObjectKey, thumbnail, map[string]string{
|
||||
"Content-Type": header.Header.Get("Content-Type"),
|
||||
@@ -249,6 +268,7 @@ func (l *UploadFileLogic) uploadFileToOSS(uid string, header *multipart.FileHead
|
||||
if err != nil {
|
||||
return "", "", errors.New("upload thumbnail file failed")
|
||||
}
|
||||
|
||||
return objectKey, thumbObjectKey, nil
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user