html input 的 accept 属性仅过滤文件选择界面,不参与校验;必须用 javascript 提取文件后缀并正则判断,注意大小写、多点名、无后缀等边界;submit 事件中校验更可靠;服务端须基于魔数二次校验。

HTML input 的 accept 属性不能替代正则校验
HTML 原生 <input type="file"> 的 accept 属性只控制文件选择器的过滤界面(比如只显示 .pdf 文件),**完全不参与表单提交前的校验逻辑**,也无法用正则表达式。用户仍可绕过界面限制手动选中任意后缀文件,甚至拖拽上传。真要校验,必须靠 JavaScript 配合正则。
用 JavaScript 的 files[0].name 匹配正则
获取文件名后,提取后缀并用 RegExp.test() 判断。关键点在于:后缀要区分大小写、处理无后缀/点号开头等边界情况。
常见错误现象:"report.PDF" 被拒绝(正则写成 /\.pdf$/i 是对的,但写成 /\.pdf$/ 就会漏掉大写);"archive.tar.gz" 被误判为 .gz 合法(其实业务可能只允许单后缀)。
实操建议:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 用
String.prototype.split('.').pop()提取最后一个点后的部分,比lastIndexOf更简洁且能覆盖"file.name.txt" - 统一转小写再比对,避免大小写陷阱:
filename.split('.').pop().toLowerCase() === 'pdf' - 正则推荐写法:
/\.(pdf|docx|xlsx)$/i,注意开头的\.和结尾的$,防止"virus.pdf.exe"通过 - 务必检查
files.length > 0,否则files[0]是undefined,调.name会报错Cannot read property 'name' of undefined
在 form submit 事件里做拦截
不要依赖 change 事件单独校验——用户可能跳过选择直接提交,或改了文件再点提交。最稳的方式是在 submit 事件里统一检查。
示例逻辑片段:
form.addEventListener('submit', (e) => {
const fileInput = document.querySelector('input[type="file"]');
if (!fileInput.files.length) return;
const ext = fileInput.files[0].name.split('.').pop().toLowerCase();
if (!/(pdf|docx|xlsx)$/.test(ext)) {
e.preventDefault();
alert('仅支持 PDF、DOCX、XLSX 文件');
}
});
服务端必须重复校验
前端正则只是用户体验优化,**完全不可信**。攻击者可禁用 JS、伪造请求、重放包,绕过所有前端限制。服务端收到文件后,必须独立检查:Content-Type 不可靠(易伪造),应读取文件魔数(magic bytes)或临时保存后用 file 命令识别真实类型,再比对后缀。
容易被忽略的地方:有些框架(如 Express + Multer)默认不限制后缀,req.file.originalname 可被任意篡改,真正可信的只有文件二进制内容本身。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










