webp fix v2
This commit is contained in:
+17
-15
@@ -668,6 +668,11 @@ type uploadImageOptions struct {
|
||||
|
||||
var ErrUploadImageSizeTooLarge = errors.New("图片文件大小不能大于 5Mb")
|
||||
|
||||
// fitsWithinSide 判断图片宽高是否都已在 maxSide 的边长限制内。
|
||||
func fitsWithinSide(cfg image.Config, maxSide int) bool {
|
||||
return cfg.Width > 0 && cfg.Height > 0 && cfg.Width <= maxSide && cfg.Height <= maxSide
|
||||
}
|
||||
|
||||
func uploadImage(ctx context.Context, opts uploadImageOptions) error {
|
||||
imgFile := opts.Image
|
||||
fileName := imgFile.Filename
|
||||
@@ -696,17 +701,16 @@ func uploadImage(ctx context.Context, opts uploadImageOptions) error {
|
||||
var contentType string
|
||||
var uploadKey string
|
||||
|
||||
// 检测原始格式(解码前先校验像素总量,防止解压炸弹)
|
||||
if err := imagecheck.CheckPixelLimit(bytes.NewReader(originalData)); err != nil {
|
||||
if errors.Is(err, imagecheck.ErrImageTooLarge) {
|
||||
return imagecheck.ErrImageTooLarge
|
||||
}
|
||||
// 检测原始格式(只解析文件头,不解像素):既拿到 format 也拿到宽高,
|
||||
// 供像素总量校验与 WebP 透传判断共用。此前此处 image.Decode 完整解码一遍
|
||||
// 只为取 format,转换时还要再解一遍,峰值内存翻倍。
|
||||
cfg, format, err := image.DecodeConfig(bytes.NewReader(originalData))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "decode image config")
|
||||
}
|
||||
|
||||
_, format, err := image.Decode(bytes.NewReader(originalData))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "decode image")
|
||||
if cfg.Width > 0 && cfg.Height > 0 &&
|
||||
int64(cfg.Width)*int64(cfg.Height) > imagecheck.MaxImagePixels {
|
||||
return imagecheck.ErrImageTooLarge
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
@@ -728,19 +732,17 @@ func uploadImage(ctx context.Context, opts uploadImageOptions) error {
|
||||
uploadKey = fmt.Sprintf("%d/%d/%d%s", now.Year(), now.Month(), now.UnixNano(), ".webp")
|
||||
}
|
||||
default:
|
||||
// JPEG / PNG 等静态图片转换为 WebP。这里只取 DecodeConfig(不波纹解像素),
|
||||
// 避免在像素量已经 CheckPixelLimit 校验过的超大图上再解码一遍。
|
||||
cfg, _, cfgErr := image.DecodeConfig(bytes.NewReader(originalData))
|
||||
// JPEG / PNG 等静态图片转换为 WebP。
|
||||
// 已是 WebP 且尺寸合规 -> 原样上传:再编码会白丢一代有损画质。
|
||||
if format == "webp" && cfgErr == nil &&
|
||||
cfg.Width <= storage.GeneralEncodeSpec.MaxSide && cfg.Height <= storage.GeneralEncodeSpec.MaxSide {
|
||||
if format == "webp" &&
|
||||
fitsWithinSide(cfg, storage.GeneralEncodeSpec.MaxSide) {
|
||||
uploadData = originalData
|
||||
contentType = "image/webp"
|
||||
uploadKey = fmt.Sprintf("%d/%d/%d%s", now.Year(), now.Month(), now.UnixNano(), fileExt)
|
||||
break
|
||||
}
|
||||
|
||||
webpData, err := storage.ConvertStaticImageToWebP(bytes.NewReader(originalData), storage.GeneralEncodeSpec)
|
||||
webpData, err := storage.ConvertStaticImageToWebP(originalData, storage.GeneralEncodeSpec)
|
||||
if err != nil || len(webpData) >= len(originalData) {
|
||||
// 转换失败,或转换后并不比原图小(小图标/线框图/已优化 JPEG 上有损 WebP
|
||||
// 可能反而更大)—— 一律沿用原图。
|
||||
|
||||
Reference in New Issue
Block a user