<p>视频文件(MP4、TS、MOV)应优先用ffprobe而非mp4ff,因ffprobe支持fragmented MP4、HEVC with HDR、QuickTime timecode等复杂场景,且能自动fallback计算duration_ts * time_base;mp4ff仅适合纯Go无依赖的box层级修改。</p>

直接上结论:别用单一库通吃所有文件类型,不同格式得用专用工具——视频用 ffprobe,图像用 imagemeta 或 chai2010/webp,MP4 结构分析用 mp4ff,而上传时的元数据只能信 multipart.FileHeader + 内容检测双保险。
视频文件(MP4、TS、MOV)该用 ffprobe 还是 mp4ff?
ffprobe 是事实标准,mp4ff 是补充手段。ffprobe 能处理 fragmented MP4、HEVC with HDR、QuickTime timecode 等 mp4ff 不支持或解析不全的场景;mp4ff 优势在于纯 Go、无依赖,适合做 box 层级修改(如加解密、裁剪初始化片段),但对 duration 为 N/A 的直播录制文件,它不会自动 fallback 到 duration_ts * time_base 计算,容易返回零值。
常见错误现象:Duration: N/A 出现在 ffprobe 输出里,但代码里直接取 format.duration 导致时长为 0;mp4ff 解析 HEVC 视频时漏掉 VPS NALU,导致播放器无法解码。
- 优先调
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4,用json.Number解析duration字段防 float64 精度丢失 - 需要改写 MP4 文件结构(如插入 SEI、加密 CENC)才用
mp4ff - 别用
mp4ff替代 ffprobe 做元数据校验——它不校验帧完整性,也不做时间戳重映射
图像文件(JPEG、WebP、AVIF、HEIC)怎么选解析库?
按格式分层选:JPEG/HEIC/TIFF/RAW 用 imagemeta,WebP 用 chai2010/webp,AVIF 目前没成熟 Go 库,得 fallback 到 http.DetectContentType + 外部命令(如 magick identify -verbose)。
立即学习“go语言免费学习笔记(深入)”;
常见错误现象:mime.TypeByExtension(".avif") 返回空字符串(Go 原生不支持);chai2010/webp.GetInfo() 对含 XMP 的 WebP 返回 hasAlpha=false(实际有),因它默认跳过非图像数据块。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
-
imagemeta支持 Exif/XMP 提取且零分配,适合高并发缩略图服务 -
chai2010/webp的webp.Decode()会完整解码,若只需宽高,用webp.GetInfo()更快 - 所有图像库都不校验文件头是否被篡改,上传场景必须先用
http.DetectContentType()读前 512 字节
HTTP 上传文件时,multipart.FileHeader 能信多少?
只信 fh.Size 和 fh.Header.Get("Content-Type")(后者仅作参考),其余字段全是“浏览器给什么就收什么”,不可用于路径拼接或权限判断。
常见错误现象:fh.Filename 是 "C:\fakepath\avatar.jpg"(IE/Edge)、""(iOS Safari)、或带 ../ 路径(恶意构造);fh.Size 显示 0 但文件内容存在(前端流式上传中断,ParseMultipartForm 只读到 header)。
- 必须先调
r.ParseMultipartForm(32 (32MB 上限),否则 <code>r.FormFilepanic - 取文件名一律用
filepath.Base(fh.Filename),再加 UUID 前缀防覆盖 -
fh.Header.Get("Content-Type")为空或application/octet-stream时,立刻用http.DetectContentType()检测真实类型 - 上传大文件务必设
maxMemory,否则可能 OOM;临时目录要提前os.MkdirAll
如何统一处理多种文件的 MIME 类型识别?
不能只靠扩展名,也不能只靠 header,必须三级校验:后缀快速过滤 → 前 512 字节内容检测 → 白名单比对。
常见错误现象:mime.TypeByExtension(".pdf") 返回 application/pdf,但文件其实是 ZIP 伪装;http.DetectContentType() 对无 magic number 的文本文件返回 text/plain,但业务只要 application/pdf。
- 先注册缺失扩展:
mime.AddExtensionType(".webp", "image/webp")(Go 1.19+ 已内置,但 .avif 仍需手动) - 读文件前 512 字节传给
http.DetectContentType(),不是整个文件 - 最终结果必须落在白名单里,例如只允许
image/*、video/mp4、application/pdf - 对视频文件,白名单检查后还得跑一次
ffprobe确认 codec_type 是 video,防止 .mp4 封装了纯音频
最易被忽略的是:视频切片后不校验可播性,图像上传后不验证 EXIF 是否被恶意注入,以及所有元数据解析都默认信任文件头长度——而实际文件可能被截断或填充垃圾字节。真正在意可靠性的服务,都会在解析后加一道 io.ReadFull 校验关键字段长度,而不是只看 err == nil。

















