Skip to content

Commit

Permalink
Merge pull request #29 from zjutjh/SugarMGP/dev
Browse files Browse the repository at this point in the history
fix: 改用io.Reader操作文件
  • Loading branch information
Penryn authored Dec 5, 2024
2 parents 8501b66 + d4e8c49 commit 53235cd
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 49 deletions.
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion app/apiException/apiException.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, "上传的文件不是图片")

Expand Down
32 changes: 20 additions & 12 deletions app/controllers/objectController/upload.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//nolint:all
package objectController

import (
"bytes"
"errors"
"io"
"mime/multipart"

"4u-go/app/apiException"
Expand All @@ -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
Expand All @@ -43,32 +50,33 @@ 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"
}
}

// 上传文件
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
}

Expand Down
54 changes: 18 additions & 36 deletions app/services/objectService/objectService.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import (
"fmt"
"io"
"mime/multipart"
"strings"
"time"

"github.com/chai2010/webp"
"github.com/disintegration/imaging"
"github.com/dustin/go-humanize"
"github.com/gabriel-vasile/mimetype"
uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
)

var (
Expand Down Expand Up @@ -43,7 +41,7 @@ var uploadTypeLimits = map[string]int64{

// GetFileInfo 获取文件基本信息
func GetFileInfo(
fileData []byte,
file multipart.File,
fileSize int64,
uploadType string,
) (
Expand All @@ -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
}

Expand All @@ -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
}

0 comments on commit 53235cd

Please sign in to comment.