accept 属性仅能默认过滤文件选择对话框中的文件类型,无法阻止用户手动切换“所有文件”后上传非法类型,真正安全限制必须依赖后端基于文件内容(如 magic bytes)的校验。

accept 属性只能过滤文件选择对话框的默认视图,不能阻止用户手动切换“所有文件”后选中非法类型——真正限制必须靠后端校验。
用 accept 让浏览器默认只显示 .txt 文件
给 <input type="file"> 加上 accept=".txt" 或更准确的 MIME 类型 accept="text/plain":
<input type="file" accept=".txt,text/plain">
这样在大多数桌面浏览器(Chrome、Edge、Firefox)打开文件选择框时,默认只列出 .txt 文件。但注意:
- Windows 上用户点下拉菜单仍可选“所有文件”,然后手动挑一个
evil.jpg也能通过 - 移动端 Safari 对
text/plain支持差,必须加.txt才生效 - 不要写成
accept="txt"——漏掉点号会完全失效
用 JavaScript 检查 files[0].name 后缀名
前端拦截体验更好,但仅作提示,不能替代后端:
document.querySelector('input[type="file"]').addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
const ext = file.name.split('.').pop().toLowerCase();
if (ext !== 'txt') {
alert('请上传 .txt 文件');
e.target.value = ''; // 清空 input,防止提交
}
});
关键点:
- 别依赖
file.type:空值、""、或误报(比如记事本另存为 ANSI 编码时可能返回text/plain,但 UTF-8 BOM 可能被识别为application/octet-stream) - 用
file.name提取扩展名最稳,大小写统一转小写再比对 - 这个检查只防手误,绕过 JS 非常容易(禁用脚本、直接发 POST 请求)
后端必须校验真实内容,不是扩展名
用户把 malware.exe 改名为 notes.txt 就能骗过所有前端检查。安全做法是读文件头(magic bytes):
- Node.js:用
file-type包解析 buffer 前几字节,确认是纯文本类 MIME(如text/plain),且不含可执行特征 - Python:用
python-magic调magic.from_buffer(),拒绝application/x-dosexec等类型 - PHP:用
finfo_open(FILEINFO_MIME_TYPE)+finfo_file(),别信$_FILES['f']['type'] - Java:Spring 中禁用
MultipartFile.getContentType(),改用Files.probeContentType()或 Tika
同时记得检查 enctype="multipart/form-data" 是否写在 <form></form> 标签上——漏了这句,后端根本收不到文件字段,错误信息常是 req.file is undefined,容易误判为前端问题。
最容易被忽略的是:前端 accept 和 JS 校验只是降低误操作率,只要没做服务端魔数校验,就等于没限制。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











