From d4e8c493a03436850683a1f26f4cf3b0d1fcb2ba Mon Sep 17 00:00:00 2001 From: SugarMGP <2350745751@qq.com> Date: Wed, 4 Dec 2024 21:19:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=B9=E7=94=A8io.Reader=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .golangci.yml | 3 ++ app/apiException/apiException.go | 2 +- app/controllers/objectController/upload.go | 32 +++++++----- app/services/objectService/objectService.go | 54 +++++++-------------- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 899a837..3d99cd8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -57,6 +57,9 @@ linters-settings: - name: function-length # 函数长度限制 severity: warning disabled: true + - name: cyclomatic # 圈复杂度 + severity: warning + disabled: true - name: cognitive-complexity # 认知复杂度 severity: warning disabled: false diff --git a/app/apiException/apiException.go b/app/apiException/apiException.go index 1b8b6d4..6776367 100644 --- a/app/apiException/apiException.go +++ b/app/apiException/apiException.go @@ -32,7 +32,7 @@ var ( ResourceNotFound = NewError(200511, log.LevelInfo, "访问的资源不存在") AdminKeyError = NewError(200512, log.LevelInfo, "管理员注册密钥错误") AdminAlreadyExisted = NewError(200513, log.LevelInfo, "管理员账号已存在") - UploadFileError = NewError(200514, log.LevelError, "上传文件失败") + UploadFileError = NewError(200514, log.LevelInfo, "上传文件失败") FileSizeExceedError = NewError(200515, log.LevelInfo, "文件大小超限") FileNotImageError = NewError(200516, log.LevelInfo, "上传的文件不是图片") diff --git a/app/controllers/objectController/upload.go b/app/controllers/objectController/upload.go index 03d67fa..f1f424f 100644 --- a/app/controllers/objectController/upload.go +++ b/app/controllers/objectController/upload.go @@ -1,8 +1,9 @@ +//nolint:all package objectController import ( - "bytes" "errors" + "io" "mime/multipart" "4u-go/app/apiException" @@ -27,14 +28,20 @@ func UploadFile(c *gin.Context) { uploadType := data.UploadType fileSize := data.File.Size - fileData, err := objectService.ReadFileToBytes(data.File) + file, err := data.File.Open() if err != nil { apiException.AbortWithException(c, apiException.UploadFileError, err) return } + defer func(file multipart.File) { + err := file.Close() + if err != nil { + zap.L().Warn("文件关闭错误", zap.Error(err)) + } + }(file) // 获取文件信息 - contentType, fileExt, err := objectService.GetFileInfo(fileData, fileSize, uploadType) + contentType, fileExt, err := objectService.GetFileInfo(file, fileSize, uploadType) if errors.Is(err, objectService.ErrSizeExceeded) { apiException.AbortWithException(c, apiException.FileSizeExceedError, err) return @@ -43,22 +50,23 @@ func UploadFile(c *gin.Context) { apiException.AbortWithException(c, apiException.ParamError, err) return } - if errors.Is(err, objectService.ErrNotImage) { - apiException.AbortWithException(c, apiException.FileNotImageError, err) - return - } if err != nil { apiException.AbortWithException(c, apiException.ServerError, err) return } + var fileReader io.Reader = file if uploadType == objectService.TypeImage { - d, s, err := objectService.ConvertToWebP(fileData) + reader, size, err := objectService.ConvertToWebP(file) if err != nil { + if errors.Is(err, objectService.ErrNotImage) { + apiException.AbortWithException(c, apiException.FileNotImageError, err) + return + } zap.L().Error("转换图片到 WebP 失败", zap.Error(err)) } else { // 若转换成功则替代原文件 - fileData = d - fileSize = s + fileReader = reader + fileSize = size fileExt = ".webp" contentType = "image/webp" } @@ -66,9 +74,9 @@ func UploadFile(c *gin.Context) { // 上传文件 objectKey := objectService.GenerateObjectKey(uploadType, fileExt) - objectUrl, err := objectService.PutObject(objectKey, bytes.NewReader(fileData), fileSize, contentType) + objectUrl, err := objectService.PutObject(objectKey, fileReader, fileSize, contentType) if err != nil { - apiException.AbortWithException(c, apiException.UploadFileError, err) + apiException.AbortWithException(c, apiException.ServerError, err) return } diff --git a/app/services/objectService/objectService.go b/app/services/objectService/objectService.go index 20a0f3a..3eeabc0 100644 --- a/app/services/objectService/objectService.go +++ b/app/services/objectService/objectService.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "mime/multipart" - "strings" "time" "github.com/chai2010/webp" @@ -14,7 +13,6 @@ import ( "github.com/dustin/go-humanize" "github.com/gabriel-vasile/mimetype" uuid "github.com/satori/go.uuid" - "go.uber.org/zap" ) var ( @@ -43,7 +41,7 @@ var uploadTypeLimits = map[string]int64{ // GetFileInfo 获取文件基本信息 func GetFileInfo( - fileData []byte, + file multipart.File, fileSize int64, uploadType string, ) ( @@ -57,13 +55,10 @@ func GetFileInfo( } // 通过文件头获取类型和扩展名 - mimeType, mimeExt := getFileTypeAndExt(fileData) - - // 检查是否为图像类型 - if uploadType == TypeImage && !strings.HasPrefix(mimeType, "image") { - return "", "", ErrNotImage + mimeType, mimeExt, err := getFileTypeAndExt(file) + if err != nil { + return "", "", err } - return mimeType, mimeExt, nil } @@ -85,42 +80,29 @@ func checkFileSize(uploadType string, size int64) error { } // getFileTypeAndExt 根据文件头(Magic Number)判断文件类型和扩展名 -func getFileTypeAndExt(fileData []byte) (mimeType string, mimeExt string) { - mime := mimetype.Detect(fileData) - return mime.String(), mime.Extension() -} - -// ConvertToWebP 将图片转换为 WebP 格式 -func ConvertToWebP(fileData []byte) ([]byte, int64, error) { - img, err := imaging.Decode(bytes.NewReader(fileData)) +func getFileTypeAndExt(file multipart.File) (mimeType string, mimeExt string, err error) { + mime, err := mimetype.DetectReader(file) if err != nil { - return nil, 0, err + return "", "", err } - - var buf bytes.Buffer - err = webp.Encode(&buf, img, &webp.Options{Quality: 100}) + _, err = file.Seek(0, io.SeekStart) if err != nil { - return nil, 0, err + return "", "", err } - return buf.Bytes(), int64(buf.Len()), nil + return mime.String(), mime.Extension(), nil } -// ReadFileToBytes 读取文件数据 -func ReadFileToBytes(fileHeader *multipart.FileHeader) ([]byte, error) { - file, err := fileHeader.Open() +// ConvertToWebP 将图片转换为 WebP 格式 +func ConvertToWebP(file multipart.File) (io.Reader, int64, error) { + img, err := imaging.Decode(file) if err != nil { - return nil, fmt.Errorf("failed to open file: %w", err) + return nil, 0, fmt.Errorf("%w: %w", ErrNotImage, err) } - defer func(file multipart.File) { - err := file.Close() - if err != nil { - zap.L().Warn("文件关闭失败", zap.Error(err)) - } - }(file) - data, err := io.ReadAll(file) + var buf bytes.Buffer + err = webp.Encode(&buf, img, &webp.Options{Quality: 100}) if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) + return nil, 0, err } - return data, nil + return bytes.NewReader(buf.Bytes()), int64(buf.Len()), nil }