webp fix v1

This commit is contained in:
tamakyi
2026-10-15 11:41:19 +08:00
parent 6ffc87e4a8
commit e4457e3da4
15 changed files with 1297 additions and 39 deletions
+36 -9
View File
@@ -712,16 +712,41 @@ func uploadImage(ctx context.Context, opts uploadImageOptions) error {
now := time.Now()
switch format {
case "gif":
// GIF 保持原样上传,不转换(动画 GIF 需要 cwebp 工具支持)
uploadData = originalData
contentType = "image/gif"
uploadKey = fmt.Sprintf("%d/%d/%d%s", now.Year(), now.Month(), now.UnixNano(), fileExt)
// 与 storage.UploadPictureToS3 走同一实现,避免同一张 GIF 在两个入口
// 得到不同格式/体积(此前此处完全跳过转换)。
webpData, err := storage.ConvertGifToAnimatedWebP(originalData)
if err != nil || len(webpData) >= len(originalData) {
if err != nil {
logrus.WithError(err).Warn("animated WebP conversion failed, falling back to original GIF")
}
uploadData = originalData
contentType = "image/gif"
uploadKey = fmt.Sprintf("%d/%d/%d%s", now.Year(), now.Month(), now.UnixNano(), fileExt)
} else {
uploadData = webpData
contentType = "image/webp"
uploadKey = fmt.Sprintf("%d/%d/%d%s", now.Year(), now.Month(), now.UnixNano(), ".webp")
}
default:
// JPEG / PNG 等静态图片转换为 WebP
webpData, err := storage.ConvertStaticImageToWebP(bytes.NewReader(originalData))
if err != nil {
// 转换失败时回退为原始数据
logrus.WithError(err).Warn("WebP conversion failed, falling back to original format")
// JPEG / PNG 等静态图片转换为 WebP。这里只取 DecodeConfig(不波纹解像素),
// 避免在像素量已经 CheckPixelLimit 校验过的超大图上再解码一遍。
cfg, _, cfgErr := image.DecodeConfig(bytes.NewReader(originalData))
// 已是 WebP 且尺寸合规 -> 原样上传:再编码会白丢一代有损画质。
if format == "webp" && cfgErr == nil &&
cfg.Width <= storage.GeneralEncodeSpec.MaxSide && cfg.Height <= 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)
if err != nil || len(webpData) >= len(originalData) {
// 转换失败,或转换后并不比原图小(小图标/线框图/已优化 JPEG 上有损 WebP
// 可能反而更大)—— 一律沿用原图。
if err != nil {
logrus.WithError(err).Warn("WebP conversion failed, falling back to original format")
}
uploadData = originalData
contentType = contentTypeFromFormat(format)
uploadKey = fmt.Sprintf("%d/%d/%d%s", now.Year(), now.Month(), now.UnixNano(), fileExt)
@@ -743,6 +768,8 @@ func uploadImage(ctx context.Context, opts uploadImageOptions) error {
Body: bytes.NewReader(uploadData),
ContentLength: aws.Int64(int64(len(uploadData))),
ContentType: aws.String(contentType),
// key 含纳秒时间戳且内容不可变,与 storage.uploadPictureToS3 保持一致的 immutable 强缓存。
CacheControl: aws.String("public, max-age=31536000, immutable"),
}); err != nil {
return errors.Wrap(err, "put object")
}