From 13ad52d09546fb225abb8bc581798b5a57a35bd4 Mon Sep 17 00:00:00 2001 From: Hiven Date: Thu, 10 Aug 2023 15:23:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/uploadfilebackendhandler.go | 76 ++-------- .../internal/logic/uploadfilebackendlogic.go | 136 ++++++++---------- server/upload/internal/types/types.go | 10 +- server_api/upload.api | 12 +- 4 files changed, 82 insertions(+), 152 deletions(-) diff --git a/server/upload/internal/handler/uploadfilebackendhandler.go b/server/upload/internal/handler/uploadfilebackendhandler.go index a3f72895..75b0b081 100644 --- a/server/upload/internal/handler/uploadfilebackendhandler.go +++ b/server/upload/internal/handler/uploadfilebackendhandler.go @@ -1,13 +1,9 @@ package handler import ( - "errors" "net/http" + "reflect" - "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/rest/httpx" - - "fusenapi/utils/auth" "fusenapi/utils/basic" "fusenapi/server/upload/internal/logic" @@ -18,72 +14,22 @@ import ( func UploadFileBackendHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var ( - // 定义错误变量 - err error - // 定义用户信息变量 - userinfo *auth.UserInfo - ) - // 解析JWT token,并对空用户进行判断 - claims, err := svcCtx.ParseJwtToken(r) - // 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息 + var req types.UploadFileBackendReq + userinfo, err := basic.RequestParse(w, r, svcCtx, &req) if err != nil { - httpx.OkJsonCtx(r.Context(), w, &basic.Response{ - Code: 401, // 返回401状态码,表示未授权 - Message: "unauthorized", // 返回未授权信息 - }) - logx.Info("unauthorized:", err.Error()) // 记录错误日志 - return - } - - if claims != nil { - // 从token中获取对应的用户信息 - userinfo, err = auth.GetUserInfoFormMapClaims(claims) - // 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息 - if err != nil { - httpx.OkJsonCtx(r.Context(), w, &basic.Response{ - Code: 401, - Message: "unauthorized", - }) - logx.Info("unauthorized:", err.Error()) - return - } - } else { - // 如果claims为nil,则认为用户身份为白板用户 - userinfo = &auth.UserInfo{UserId: 0, GuestId: 0} - } - - var req types.RequestUploadFileBackend - // 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据 - if err := httpx.Parse(r, &req); err != nil { - httpx.OkJsonCtx(r.Context(), w, &basic.Response{ - Code: 510, - Message: "parameter error", - }) - logx.Info(err) - return - } - - // 解析upload文件类型 - err = basic.RequestFileParse(r, &req) - if err != nil { - httpx.OkJsonCtx(r.Context(), w, &basic.Response{ - Code: 510, - Message: err.Error(), - }) return } // 创建一个业务逻辑层实例 - l := logic.NewUploadFileBackendLogic(r.Context(), svcCtx) + l := logic.NewUploadFileBackendLogic(r, svcCtx) + + rl := reflect.ValueOf(l) + basic.BeforeLogic(w, r, rl) + resp := l.UploadFileBackend(&req, userinfo) - // 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应; - if resp != nil { - httpx.OkJsonCtx(r.Context(), w, resp) - } else { - err := errors.New("server logic is error, resp must not be nil") - httpx.ErrorCtx(r.Context(), w, err) - logx.Error(err) + + if !basic.AfterLogic(w, r, rl, resp) { + basic.NormalAfterLogic(w, r, resp) } } } diff --git a/server/upload/internal/logic/uploadfilebackendlogic.go b/server/upload/internal/logic/uploadfilebackendlogic.go index 77de1f5f..32a577c8 100644 --- a/server/upload/internal/logic/uploadfilebackendlogic.go +++ b/server/upload/internal/logic/uploadfilebackendlogic.go @@ -3,18 +3,16 @@ package logic import ( "fusenapi/utils/auth" "fusenapi/utils/basic" - "fusenapi/utils/check" - "fusenapi/utils/format" - "time" + "fusenapi/utils/file" + "fusenapi/utils/hash" + "io" + "net/http" "context" "fusenapi/server/upload/internal/svc" "fusenapi/server/upload/internal/types" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/service/s3" "github.com/zeromicro/go-zero/core/logx" ) @@ -22,109 +20,91 @@ type UploadFileBackendLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext + r *http.Request } -func NewUploadFileBackendLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadFileBackendLogic { +func NewUploadFileBackendLogic(r *http.Request, svcCtx *svc.ServiceContext) *UploadFileBackendLogic { return &UploadFileBackendLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, + Logger: logx.WithContext(r.Context()), + ctx: r.Context(), svcCtx: svcCtx, + r: r, } } -// UploadFileBackend 这个函数接收一个文件上传请求和用户信息,处理文件上传,并返回响应 -func (l *UploadFileBackendLogic) UploadFileBackend(req *types.RequestUploadFileBackend, userinfo *auth.UserInfo) (resp *basic.Response) { +// 处理进入前逻辑w,r +// func (l *UploadFileBackendLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { +// } +// 处理逻辑后 w,r 如:重定向, resp 必须重新处理 +// func (l *UploadFileBackendLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { +// // httpx.OkJsonCtx(r.Context(), w, resp) +// } + +func (l *UploadFileBackendLogic) UploadFileBackend(req *types.UploadFileBackendReq, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null - - // 检查用户是否是旁观者,旁观者没有文件上传权限 if userinfo.IsOnlooker() { // 如果是,返回未授权的错误码 return resp.SetStatus(basic.CodeUnAuth) } // 定义用户ID和S3键名格式 - var uid int64 - var keytype format.TypeFormatS3KeyName + var userId int64 + var guestId int64 // 检查用户是否是游客 if userinfo.IsGuest() { // 如果是,使用游客ID和游客键名格式 - uid = userinfo.GuestId - keytype = format.TypeS3KeyGuest + guestId = userinfo.GuestId } else { // 否则,使用用户ID和用户键名格式 - uid = userinfo.UserId - keytype = format.TypeS3KeyUser + userId = userinfo.UserId } - // 设置AWS会话的区域 - l.svcCtx.AwsSession.Config.Region = aws.String("us-west-1") + //设置内存大小 + l.r.ParseMultipartForm(32 << 20) - // 创建新的S3服务实例 - svc := s3.New(l.svcCtx.AwsSession) - - // 检查类别是否合法 - if !check.CheckCategory(req.Category) { - // 如果不合法,返回类别错误的错误码 - return resp.SetStatus(basic.CodeS3CategoryErr) - } - - // 定义S3请求和当前时间 - var s3req *request.Request - now := time.Now() - - // 格式化类别 - category := format.TypeCategory(req.Category) - - // 格式化S3对象键名 - ObjectKey := aws.String(format.FormatS3KeyName( - keytype, - uid, - now, - l.svcCtx.Config.Env, - category, - req.File.Filename, - )) - - // 定义存储桶名称 - var bucketName *string - - // 根据类别选择存储桶 - switch category { - case format.TCategoryRenderMegre: - bucketName = basic.TempfileBucketName - default: - bucketName = basic.StorageBucketName - } - - // 创建S3对象存储请求 - s3req, _ = svc.PutObjectRequest( - &s3.PutObjectInput{ - Bucket: bucketName, - Key: ObjectKey, - }, - ) - - // 设置请求体为文件数据 - s3req.SetBufferBody(req.File.Data) - - // 发送请求 - err := s3req.Send() - - // 检查是否有错误 + fileObject, _, err := l.r.FormFile("file") if err != nil { - // 如果有,打印错误并返回错误码 logx.Error(err) - return resp.SetStatus(basic.CodeS3PutObjectRequestErr) + return resp.SetStatus(basic.CodeFileUploadErr, "file upload err,no files") } - // 打印请求URL - logx.Info(s3req.HTTPRequest.URL.String()) + // 读取数据流 + ioData, err := io.ReadAll(fileObject) + if err != nil { + logx.Error(err) + return resp.SetStatus(basic.CodeFileUploadErr, "file upload err,no files") + } + + // 上传文件 + var upload = file.Upload{ + Ctx: l.ctx, + MysqlConn: l.svcCtx.MysqlConn, + AwsSession: l.svcCtx.AwsSession, + } + var resourceId string = hash.JsonHashKey(req.FileKey) + uploadRes, err := upload.UploadFileByByte(&file.UploadBaseReq{ + FileHash: resourceId, + FileByte: ioData, + UploadBucket: req.UploadBucket, + ApiType: req.ApiType, + UserId: userId, + GuestId: guestId, + }) + + if err != nil { + logx.Error(err) + return resp.SetStatus(basic.CodeFileUploadErr, "upload file failed") + } // 返回成功的响应和上传URL return resp.SetStatus(basic.CodeOK, map[string]interface{}{ - "upload_url": s3req.HTTPRequest.URL.String(), + "upload_data": UploadUrl{ + Status: 1, + ResourceId: uploadRes.ResourceId, + ResourceUrl: uploadRes.ResourceUrl, + }, }) } diff --git a/server/upload/internal/types/types.go b/server/upload/internal/types/types.go index bb635925..b6363f9f 100644 --- a/server/upload/internal/types/types.go +++ b/server/upload/internal/types/types.go @@ -23,10 +23,12 @@ type UploadLogoReq struct { SkuId int64 `form:"sku_id,default=0"` // 模板ID } -type UploadInfo struct { - FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息 - FileKeys string `form:"file_keys,optional"` // 上传唯一标识信息 - Metadata string `form:"meta_data,optional"` // 上传文件额外信息 +type UploadFileBackendReq struct { + ApiType int64 `form:"api_type,options=[1,2],default=1"` // 调用类型:1=对外,2=对内 + UploadBucket int64 `form:"upload_bucket,options=[1,2],default=1"` // 上传桶名:1=缓存,2=持久 + FileKey string `form:"file_key"` // 上传唯一标识信息 + FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息 + Metadata string `form:"meta_data,optional"` // 上传文件额外信息 } type UploadFilesReq struct { diff --git a/server_api/upload.api b/server_api/upload.api index d8479feb..a9581adf 100644 --- a/server_api/upload.api +++ b/server_api/upload.api @@ -17,7 +17,7 @@ service upload { post /api/upload/upload-file-frontend(RequestUploadFileFrontend) returns (response); @handler UploadFileBackendHandler - post /api/upload/upload-file-backend(RequestUploadFileBackend) returns (response); + post /api/upload/upload-file-backend(UploadFileBackendReq) returns (response); //生成二维码 @handler UploadQrcodeHandler post /api/upload/qrcode(UploadQrcodeReq) returns (response); @@ -67,10 +67,12 @@ type ( ) type ( - UploadInfo { - FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息 - FileKeys string `form:"file_keys,optional"` // 上传唯一标识信息 - Metadata string `form:"meta_data,optional"` // 上传文件额外信息 + UploadFileBackendReq { + ApiType int64 `form:"api_type,options=[1,2],default=1"` // 调用类型:1=对外,2=对内 + UploadBucket int64 `form:"upload_bucket,options=[1,2],default=1"` // 上传桶名:1=缓存,2=持久 + FileKey string `form:"file_key"` // 上传唯一标识信息 + FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息 + Metadata string `form:"meta_data,optional"` // 上传文件额外信息 } UploadFilesReq {