先记住这个答案
<input type="file"> 的 accept 主要影响文件选择器的候选过滤,可写扩展名、MIME 类型或类似 image/* 的范围。multiple 让用户一次选择多个文件,结果在控件的 files 中。它们是交互提示与数量能力,不能保证上传内容真实符合要求;服务端必须再次检查。
accept是选择提示,不是安全校验multiple允许一次选多个文件- 读取结果应遍历
files - 后端仍要检查大小与真实类型
用户选择阶段能做什么
头像上传可以写 accept="image/png,image/jpeg",减少用户误选文档的机会。若业务允许多个附件,加上 multiple;否则控件通常只接受单个选择。accept 不是不可绕过的白名单,一些选择器允许改成查看所有文件,脚本也可构造网络请求。
<form action="/photos" method="post" enctype="multipart/form-data">
<label for="photos">照片</label>
<input id="photos" name="photos" type="file"
accept="image/png,image/jpeg" multiple>
<button type="submit">上传</button>
</form>有文件的原生 POST 表单通常使用 multipart/form-data。读取控件时看 files 列表,不要把 value 当成真实本地路径。出于隐私与安全原因,浏览器不会把任意本地文件路径交给网页。
服务端不能信任文件名
扩展名可以改,客户端宣称的 MIME 类型也可能与文件实际内容不一致。服务器应设置文件大小、数量、允许类型、存储位置和后续处理规则;图片处理链路还应确认内容可被安全解码。
如果前端用 FormData 加 fetch 上传,多文件可逐项加入同一个字段名,或按接口契约使用不同字段名。后端应与前端约定清楚“一个字段多个文件”的解析形式,不要仅因控件加了 multiple 就假设服务器会自动支持。
accept="image/png,image/jpeg" 影响文件选择器给用户展示哪些候选文件,不是安全校验。用户可能通过其他途径构造请求,文件扩展名和浏览器报告的 File.type 也不能当作可信证据。multiple 只允许选多份文件;同名字段提交时会带多项,服务端要逐个检查大小、格式和数量。若页面要展示所选文件,读取 input.files 而不是试图解析 input.value,后者通常只是伪路径,不代表真实本地路径。
容易答错的地方
- 把
accept当成上传安全防线 - 它只是选择器提示,网络请求可以绕过;后端必须独立校验。
- 用
input.value当作本地文件路径 - 浏览器不会开放真实路径;要处理文件对象应读
files。
面试官还会怎么问?
accept="image/*" 是允许任意图片吗?
它提示选择器展示图片类型,具体候选由环境决定;服务端仍应列出实际允许的格式。
如何知道用户选了几个文件?
检查控件的 files.length,再逐个读取文件对象的名称、大小等信息。
文件表单为什么使用 multipart?
它按分段传输普通字段与文件内容,能保留文件所需的信息。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。