fix: 回退存储路径也解码重编码,彻底剥离 EXIF/元数据

- fallback 路径不再直接写原始上传字节,而是解码后重编码
- JPEG: decode → jpeg.Encode(quality 92),剥离 EXIF/GPS/注释
- PNG: decode → png.Encode,剥离元数据块
- WebP: decode → webp.Encode(quality 80),剥离元数据
- GIF 例外:重编码会丢失动画帧,仅解码验证后原样存储
- 导入 jpeg/png 从空白导入改为命名导入,以使用 Encode 函数
This commit is contained in:
2026-05-31 03:12:10 +08:00
parent d8e58b5f8c
commit 48186085d8

View File

@ -5,9 +5,9 @@ import (
"errors"
"fmt"
"image"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"image/jpeg"
"image/png"
_ "image/gif" // 仅注册 GIF 解码器,不重编码(会丢失动画)
"io"
"net/http"
"os"
@ -449,11 +449,38 @@ func (ctrl *PostController) UploadImage(c *gin.Context) {
}
}
// 原格式存储GIF / 已有 WebP / 二分压缩仍超原文件大小
// 回退存储:重新编码以剥离 EXIF/元数据GIF 例外:重编码会丢失动画
if savePath == "" {
dataOut := data
if isJPEGPNG || isWebP {
var decImg image.Image
var decErr error
if isWebP {
decImg, decErr = webp.Decode(bytes.NewReader(data))
} else {
decImg, _, decErr = image.Decode(bytes.NewReader(data))
}
if decErr == nil {
var buf bytes.Buffer
var encErr error
switch {
case isWebP:
encErr = webp.Encode(&buf, decImg, &webp.Options{Quality: 80})
case ext == ".png":
encErr = png.Encode(&buf, decImg)
default:
encErr = jpeg.Encode(&buf, decImg, &jpeg.Options{Quality: 92})
}
if encErr == nil && buf.Len() > 0 {
dataOut = buf.Bytes()
}
}
}
filename := fmt.Sprintf("%d_%d%s", uid, ts, ext)
savePath = filepath.Join(storageDir, filename)
if err := os.WriteFile(savePath, data, 0644); err != nil {
if err := os.WriteFile(savePath, dataOut, 0644); err != nil {
common.Error(c, http.StatusInternalServerError, "保存图片失败")
return
}