严重修复:图片压缩参数被应用到了视频上,导致视频播不了 (#56)

用户报(2026-11-05):「你好像把 .mp4 后面也带上了问号,写成了 1600
这样的参数…你刚才没有进行图片压缩的时候,我自己播放好像还是好的。
是你更新了这个功能之后,出了这个问题。」

用户完全正确,这是我的错。

根因:media.php 只看 $imgW,没判是不是图片:
  Storage::read($familyId, $key, $imgW > 0 ? $OssSizes[$imgW] : );
⇒ 视频 URL 带 ?w=1600 后,给 .mp4 对象传了
  x-oss-process=image/resize,l_1600
⇒ OSS 图片处理服务对非图片返回错误内容
⇒ <video> 拿不到有效数据 ⇒ 播不了

三道防线:

1. _attachments.php(直接触发点)
   原来对所有附件都传 w=1600。改为 $attKind === image 才传。
   视频只传 v(版本号,破缓存用)。

2. media.php(核心防线)
   $imgW 与 $isImageKey 绑定,只有图片才允许压缩。
   $isImageKey 判定提前到 Storage::read 之前,
   并扩到扩展名兜底(jpg/png/webp...),
   视频/文档扩展名强制 false。

3. media_url()(前置防线)
   生成 URL 时按扩展名过滤:非图片自动去掉 w。
   这样即使调用方传错,URL 里也不会出现无效参数。

验证(模拟事故场景,URL 带 ?w=1600 请求 .mp4):
  HTTP 206,Content-Type: video/mp4
  无 hvc1,含 avc1
  ffprobe: h264/yuv420p,2.19MB  ✅ 正常

  media_url 生成视频 URL:...mp4&v=2295119(无 w)
  media_url 生成图片 URL:...jpg&w=1600&v=609017(有 w)
This commit is contained in:
2026-11-05 13:14:51 +08:00
parent 2c44318a51
commit bee1d077d8
3 changed files with 70 additions and 10 deletions
+14 -8
View File
@@ -49,14 +49,20 @@ $attDelUrl = $attDelUrl ?? '';
<?php
$attKind = \App\Attachment::kind($attRow);
$canPrev = \App\Attachment::previewable($attRow);
/* 🔴 #56(用户:「400压缩的太多了。800也不够,只保留一个1600。」)
照片墙改用 1600 档 —— 缩略图看着小,但点开就是大图,
用同一份缓存比"缩略图 400 + 大图 1600"两套更省事,
而且手机上不会糊。
⚠️ 下载链接($attDl)**不加** w:要原文件,不能偷偷降质。 */
/* #57:第三个参数传 size 当版本号 —— 转码后体积变了,URL 就变,
浏览器不会再用旧的 HEVC 缓存。 */
$attView = media_url((string)$attRow['key'], ['w' => 1600],
/* 🔴🔴 #56(用户 2026-11-05:「你好像把 .mp4 后面也带上了问号,
写成了 1600 这样的参数…是你更新了这个功能之后,出了这个问题」)
**压缩档位只能给图片。** 原来这里对**所有附件**都传 `w=1600`:
视频 URL 变成 `media.php?k=xxx.mp4&w=1600` ⇒ OSS 收到
`x-oss-process=image/resize,l_1600` 去处理 .mp4 ⇒ 返回错误内容
⇒ `<video>` 拿不到有效数据 ⇒ **播不了**。
⇒ `$attKind === 'image'` 才传 `w`。
⚠️ `v`(版本号)**所有类型都传** —— 视频转码后靠它破缓存。
⚠️ 下载链接 `$attDl` 一律不带 `w`(要原文件,不能偷偷降质)。 */
$attOpts = $attKind === 'image' ? ['w' => 1600] : [];
$attView = media_url((string)$attRow['key'], $attOpts,
(int)($attRow['size'] ?? 0));
$attDl = media_url((string)$attRow['key'], ['dl' => 1]);
$attNm = (string)($attRow['name'] ?? '');