You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by li...@apache.org on 2024/01/30 08:16:22 UTC

(incubator-answer) 01/01: refactor(file): refactor file format check function

This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a commit to branch refactor/file
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git

commit cf4e05fbc653e1888cd895e44fc4608af15a458f
Author: LinkinStars <li...@foxmail.com>
AuthorDate: Tue Jan 30 16:16:07 2024 +0800

    refactor(file): refactor file format check function
---
 internal/service/uploader/upload.go |  2 +-
 pkg/checker/file_type.go            | 77 +++++++++++++++++++++++++++++--------
 2 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/internal/service/uploader/upload.go b/internal/service/uploader/upload.go
index fb0b2af0..3619a6e1 100644
--- a/internal/service/uploader/upload.go
+++ b/internal/service/uploader/upload.go
@@ -244,7 +244,7 @@ func (us *uploaderService) uploadFile(ctx *gin.Context, file *multipart.FileHead
 	}
 	defer src.Close()
 
-	if !checker.IsSupportedImageFile(src, filepath.Ext(fileSubPath)) {
+	if !checker.IsSupportedImageFile(filePath) {
 		return "", errors.BadRequest(reason.UploadFileUnsupportedFileFormat)
 	}
 
diff --git a/pkg/checker/file_type.go b/pkg/checker/file_type.go
index 3599270a..6c61dca2 100644
--- a/pkg/checker/file_type.go
+++ b/pkg/checker/file_type.go
@@ -20,13 +20,18 @@
 package checker
 
 import (
-	"golang.org/x/image/webp"
+	"fmt"
 	"image"
 	_ "image/gif" // use init to support decode jpeg,jpg,png,gif
 	_ "image/jpeg"
 	_ "image/png"
 	"io"
+	"os"
+	"path/filepath"
 	"strings"
+
+	"github.com/segmentfault/pacman/log"
+	"golang.org/x/image/webp"
 )
 
 const (
@@ -35,47 +40,85 @@ const (
 
 // IsSupportedImageFile currently answers support image type is
 // `image/jpeg, image/jpg, image/png, image/gif, image/webp`
-func IsSupportedImageFile(file io.Reader, ext string) bool {
-	ext = strings.ToLower(strings.TrimPrefix(ext, "."))
-	var err error
+func IsSupportedImageFile(localFilePath string) bool {
+	ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(localFilePath), "."))
 	switch ext {
 	case "jpg", "jpeg", "png", "gif": // only allow for `image/jpeg,image/jpg,image/png, image/gif`
-		if !checkImageSize(file) {
+		if !decodeAndCheckImageFile(localFilePath, standardImageConfigCheck) {
+			return false
+		}
+		if !decodeAndCheckImageFile(localFilePath, standardImageCheck) {
 			return false
 		}
-		_, _, err = image.Decode(file)
 	case "ico":
 		// TODO: There is currently no good Golang library to parse whether the image is in ico format.
 		return true
 	case "webp":
-		if !checkWebpSize(file) {
+		if !decodeAndCheckImageFile(localFilePath, webpImageConfigCheck) {
+			return false
+		}
+		if !decodeAndCheckImageFile(localFilePath, webpImageCheck) {
 			return false
 		}
-		_, err = webp.Decode(file)
 	default:
 		return false
 	}
-	return err == nil
+	return true
 }
 
-func checkImageSize(file io.Reader) bool {
-	config, _, err := image.DecodeConfig(file)
+func decodeAndCheckImageFile(localFilePath string, checker func(io.Reader) error) bool {
+	file, err := os.Open(localFilePath)
 	if err != nil {
+		log.Errorf("open file error: %v", err)
 		return false
 	}
-	if (config.Width * config.Height) > maxImageSize {
+	defer file.Close()
+
+	if err = checker(file); err != nil {
+		log.Errorf("check image format error: %v", err)
 		return false
 	}
 	return true
 }
 
-func checkWebpSize(file io.Reader) bool {
+func standardImageConfigCheck(file io.Reader) error {
+	config, _, err := image.DecodeConfig(file)
+	if err != nil {
+		return fmt.Errorf("decode image config error: %v", err)
+	}
+	if imageSizeTooLarge(config) {
+		return fmt.Errorf("image size too large")
+	}
+	return nil
+}
+
+func standardImageCheck(file io.Reader) error {
+	_, _, err := image.Decode(file)
+	if err != nil {
+		return fmt.Errorf("decode image error: %v", err)
+	}
+	return nil
+}
+
+func webpImageConfigCheck(file io.Reader) error {
 	config, err := webp.DecodeConfig(file)
 	if err != nil {
-		return false
+		return fmt.Errorf("decode webp image config error: %v", err)
 	}
-	if (config.Width * config.Height) > maxImageSize {
-		return false
+	if imageSizeTooLarge(config) {
+		return fmt.Errorf("image size too large")
 	}
-	return true
+	return nil
+}
+
+func webpImageCheck(file io.Reader) error {
+	_, err := webp.Decode(file)
+	if err != nil {
+		return fmt.Errorf("decode webp image error: %v", err)
+	}
+	return nil
+}
+
+func imageSizeTooLarge(config image.Config) bool {
+	return config.Width*config.Height > maxImageSize
 }