accept="image/*"仅控制文件选择器默认显示,无法阻止用户选择非图片文件或伪造后缀,必须结合file.type、文件后缀正则匹配及file.size三重校验,并在验证失败后清空input.value以确保change事件正常触发。

仅靠 accept 属性无法真正筛选图片类型,它只影响文件选择器的默认显示,不能阻止用户手动选非图文件或伪造后缀。必须配合 JavaScript 做二次校验,否则前端验证形同虚设。
为什么 accept="image/*" 不够用
这个属性只是浏览器 UI 提示:告诉系统“默认只显示图片类文件”。但用户能点下拉菜单切到“所有文件”,然后选一个 fake.png.exe 或 report.pdf。更麻烦的是:
- IE9 及更早版本完全忽略
accept - 某些安卓 WebView 中
accept失效,file.type恒为空字符串 - 用户把
scan.jpeg.txt改成scan.jpg,file.type仍可能返回image/jpeg,实际不是图
file.type 和 file.name 怎么组合判断
优先用 file.type 快速过滤,再用后缀兜底。不要只依赖其中一种:
- 先检查
file.type && file.type.startsWith('image/')—— 最轻量,覆盖大多数正常情况 - 若
file.type为空(移动端常见),退而匹配file.name.toLowerCase().match(/\.[a-z0-9]+$/)提取后缀 - 用正则测试后缀是否在白名单里:
/\.(jpg|jpeg|png|gif|bmp|webp)$/i,注意加i标志忽略大小写 - 避免用
file.name.endsWith('.jpg')—— 无法识别PHOTO.JPG或logo.JPEG
示例函数:
function isValidImage(file) {
if (file.type && file.type.startsWith('image/')) return true;
const ext = file.name.toLowerCase().match(/\.[a-z0-9]+$/);
return ext && /\.(jpg|jpeg|png|gif|bmp|webp)$/i.test(ext[0]);
}
别漏掉 file.size 和 input.value 清空
校验大小必须放在 change 事件里,且失败后要立刻清空 input.value,否则同一文件重复选不会触发事件:
- 大小比较用字节:比如
file.size > 5 * 1024 * 1024(5MB),别用浮点除法(file.size / 1024 / 1024 > 5)防精度误差 - 校验失败后必须执行
event.target.value = '',否则 DOM 值没变,下次选相同文件不触发change - 读取
file要在change回调里即时取event.target.files[0],别缓存到外部变量——FileList 是实时引用
真正可靠的图片类型筛选,是 file.type + 后缀正则 + file.size 三者缺一不可,而且每次 change 都得重做。魔数校验(如用 FileReader 读前几个字节)只在安全要求极高时才加,日常场景这三层已足够。最常被忽略的其实是清空 input.value 这一步,导致调试时以为逻辑没跑,其实是事件根本没触发。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











