Skip to content

Commit

Permalink
refactor(file): refactor file format check function
Browse files Browse the repository at this point in the history
  • Loading branch information
LinkinStars committed Jan 30, 2024
1 parent 968f23d commit 0849e8f
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 18 deletions.
2 changes: 1 addition & 1 deletion internal/service/uploader/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
77 changes: 60 additions & 17 deletions pkg/checker/file_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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
}

0 comments on commit 0849e8f

Please sign in to comment.