accept属性仅控制文件选择框默认筛选,无法阻止非法文件上传;必须前后端双重校验,前端用扩展名+magic bytes检测,后端以二进制流magic bytes为唯一可信依据。

accept 属性根本拦不住非法文件,它只管选择框默认显示什么
加了 accept="image/*" 后用户依然能点“所有文件”选一个 shell.php,拖拽上传、用 curl 直传、删掉 DOM 中的 accept 属性——全都能绕过。iOS Safari 可能因此禁用相册入口,华为 EMUI 和小米 MIUI 的 WebView 常直接忽略该属性。这不是 bug,是浏览器有意为之的安全设计:前端不能也不该承担校验责任。
accept 值写错就等于没写,MIME 与扩展名必须双写且无空格
单写 application/pdf 或单写 .pdf 都容易失效。Safari(尤其 iOS)依赖 MIME 类型,安卓 WebView 对扩展名支持弱,Windows 可能上报 application/x-pdf 而非标准值。
-
accept="application/pdf,.pdf"✅ 同时覆盖 MIME 和扩展名,兼容性最稳 -
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,.xlsx"✅ .xlsx 的唯一可靠组合 -
accept="image/png,image/jpeg,.png,.jpg,.jpeg"✅ 显式列出变体,避免image/pjpeg被漏 -
accept="text/plain,.csv"✅ 逗号后无空格,旧版 Safari 才不会丢弃整个属性 -
accept="application/pdf , .pdf"❌ 逗号后有空格 → Safari 解析失败
前端 JS 必须遍历每个 File 对象,别信 file.type
file.type 是浏览器推测值,可为空、可伪造。把 malware.exe 改名成 report.jpg,file.type 就可能变成 image/jpeg,但内容仍是可执行文件。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 先用
file.name.toLowerCase().endsWith('.pdf')快速过滤明显违规扩展名 - 再用
FileReader读取前 4 字节比对 magic bytes:%PDF对应[0x25, 0x50, 0x44, 0x46],PNG对应[0x89, 0x50, 0x4E, 0x47] - 提示要具体:“已选 2 个不支持的文件(
scan.tif,data.zip)”,而不是笼统说“类型错误” - 用户一次勾选多个文件时,
event.target.files里可能混着合法与非法文件,必须遍历每一项,不能只检查第一个
后端才是唯一可信边界,magic bytes 比文件名和请求头都重要
前端所有限制都可被绕过:curl、Postman、DevTools 修改 DOM、拖拽 Drop 区域……服务端收到的 Content-Type 请求头可伪造,req.file.mimetype(Node.js)或 $_FILES['file']['type'](PHP)都不可信。
- 必须读取文件二进制流前几个字节(magic bytes):
PDF开头必须是%PDF,XLSX是PK\x03\x04,PNG是\x89PNG - 推荐库:
Node.js用file-type,Python用python-magic,Java用Apache Tika - 验证扩展名是否与真实内容一致(防伪装),保存时剥离原始扩展名,用服务端生成的随机名 + 白名单后缀
- 上传目录禁止执行权限,静态资源走 CDN 或独立域名
最容易被忽略的是:即使前端 JS 用 File.type 判断,该字段由浏览器根据文件名或头部推测,不可信;服务端若只校验扩展名或请求头,就等于把门锁换成了贴纸。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










