accept 属性仅作前端提示,无法真正禁止非法文件上传;必须结合 javascript 实时校验(优先检查 file.name 扩展名)与后端白名单双重拦截。

accept 属性只能提示、不能禁止——浏览器会过滤文件选择对话框里的可见项,但用户仍可手动输入路径或拖入任意文件。真要“禁止”,必须靠 JavaScript 校验 + 后端白名单双重拦截。
用 accept 做前端友好提示
它不阻止上传,但能减少误选概率。常见写法有三类:
- MIME 类型:比如
accept="image/jpeg,image/png",Safari 和 Chrome 识别较好;accept="image/*"覆盖更广,但可能包含 WebP、AVIF 等老旧浏览器不支持的格式 - 扩展名:比如
accept=".jpg,.jpeg,.png",兼容性最稳,但依赖用户没改后缀(如把shell.php改成shell.jpg) - 混合写法:比如
accept="image/jpeg,image/png,.jpg,.jpeg,.png",兼顾 MIME 和扩展名,推荐用于关键业务
注意:accept 对 multiple 有效,但 iOS Safari 旧版本(≤16.4)对扩展名支持弱,优先用 MIME 类型。
JavaScript 实时拦截非法文件
监听 input 的 change 事件,在用户选中后立刻检查,比等表单提交再报错体验更好。
- 别只信
file.type:它由浏览器根据扩展名或文件头推测,可被伪造;例如一个 .exe 文件改名为 .jpg,file.type可能返回image/jpeg - 优先校验
file.name扩展名:用file.name.toLowerCase().endsWith('.jpg')比正则更轻量,也防大小写绕过 - 组合判断更稳妥:比如要求同时满足
.jpg后缀 +file.type === 'image/jpeg'+file.size - 发现非法文件立即清空
input.files:设input.value = '',否则后续 FormData 仍会带上它
后端才是真正的“禁止”执行者
前端一切校验都可绕过,服务器必须重新验证。PHP 示例中关键点:
- 不用
$_FILES['file']['type']做唯一依据:它来自客户端,不可信 - 用
pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)提取扩展名,再转小写,和白名单数组比对(用in_array()) - 必要时读文件头(魔术字节):比如 JPEG 是
FF D8 FF,PNG 是89 50 4E 47,用fread(fopen(...), 4)判断 - 调用
getimagesize()或exif_imagetype()验证是否为真实图片——这两者会实际解析文件内容,绕过纯后缀欺骗 - 最后才调用
move_uploaded_file();任何一步失败就exit或返回 400 错误
最容易被忽略的是:即使前端写了 accept="image/*",用户仍可能拖进一个 .pdf 或 .zip。真正起作用的永远是后端那几行白名单判断和文件头校验——前端只是帮用户少点几次“取消”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











