accept 属性无法过滤音视频编码格式,仅能按容器或 MIME 类型初筛;高精度校验必须依赖服务端解析,如用 ffprobe 提取 codec_name 并白名单比对。

accept 属性对音视频编码格式无效,只能过滤容器或 MIME 类型
直接用 accept 限制 H.264、HEVC、AV1 等编码格式是不可能的。浏览器根本不读取文件内部编码信息,accept 只能匹配文件扩展名(如 .mp4)或容器级 MIME 类型(如 video/mp4),而同一个容器(比如 MP4)可以封装 H.264、H.265、AV1 甚至 VP9 —— 浏览器无法区分。
常见错误现象:设置 accept="video/mp4" 后用户仍上传了 HEVC 编码的 MP4 文件,但前端播放失败或后端解码报错。
-
video/mp4表示“MP4 容器”,不等于“H.264 编码” -
video/webm可含 VP8、VP9 或 AV1,浏览器不校验实际编码 -
video/ogg通常对应 Theora 视频 + Vorbis 音频,但也可被篡改
真正可行的高精度过滤必须依赖服务端解析
想确认是否为 H.264 编码的 MP4,唯一可靠方式是上传后读取二进制头或调用 FFmpeg 解析流信息。前端 accept 最多做到“容器初筛”,不能替代编码级校验。
实操建议:
- 前端用
accept="video/mp4,video/webm,video/ogg"缩小选择范围,提升体验 - 服务端收到文件后,用
ffprobe -v quiet -show_entries stream=codec_name,width,height -of default提取编码器名称和分辨率 - 对关键字段做白名单判断,例如只允许
codec_name=avc(H.264)或codec_name=hevc(H.265) - 避免仅依赖
file.type,它常为空或伪造(如把 HEVC MP4 改后缀为 .mp4 就骗过浏览器)
HEIC/WebP 等现代格式需显式声明 MIME + 扩展名组合
HEIC 和 WebP 在不同浏览器中识别不稳定,单靠 MIME 或单靠扩展名都可能失效。必须两者并列声明,且注意大小写与拼写细节。
推荐写法:
- WebP:
accept="image/webp,.webp"(Safari 14+、Chrome、Edge 均支持) - HEIC:
accept="image/heic,.heic,image/heif,.heif"(iOS Safari 支持heic,macOS 部分版本认heif) - 不要写
image/*代替,它会漏掉 HEIC/WebP(很多浏览器未将其纳入通配规则) - 测试发现:Firefox 目前仍不支持 HEIC,即使写了
accept也无过滤效果,需在 JS 中提示“暂不支持”
音视频上传必须搭配二次校验逻辑
用户点击“所有文件”就能绕过 accept 界面限制,这是设计使然,不是 bug。任何生产环境都必须补上服务端验证环节。
容易踩的坑:
- 只校验
file.name后缀,忽略大小写(.HEIC≠.heic)和隐藏扩展名(如photo.jpg.webp) - 信任
file.type字段,但它由浏览器根据扩展名推测,不可靠 - 用正则匹配
file.name却没处理路径分隔符(Windows 是\,Linux/macOS 是/),导致name.split('.').pop()出错 - 未考虑 iOS 自动转换:用户从相册选 HEIC,Safari 可能转成 JPEG 再上传,此时
accept设了.heic反而拦不住真实格式
最简健壮校验逻辑:统一转小写 → 提取扩展名 → 查白名单;同时服务端用工具解析实际编码参数。这两步缺一不可。

















