必须写<input type="file" multiple>才能开启多选,multiple是布尔属性,拼写错误、加引号赋值或重复书写均无效;选多个文件后event.target.files仅返回1个通常因事件绑定错误或误用click事件,正确方式是在change事件中用Array.from(event.target.files)读取FileList。

HTML <input type="file"> 怎么开启多选?
必须加 multiplemultiple 属性,不是 multiple 拼错,也不是加两次 multiple。浏览器只认这个拼写,少一个 e 或多一个空格都不生效。
常见错误是写成 multiple="true" 或 multiple="multiple" —— 这些都无效,multiplemultiple 是布尔属性,只存在即启用。
-
<input type="file" multiple>✅ 正确 -
<input type="file" multiple="true">❌ 不起作用 -
<input type="file" multiplemultiple>❌ 拼写错误,被忽略
为什么选了多个文件,event.target.files 却只有 1 个?
通常是因为监听了 change 事件但没处理好事件对象,或误用了 click 事件。真正承载文件列表的是 event.target.files(FileList 对象),它天然支持多选,但必须在 change 触发后立刻读取。
容易踩的坑:files 是只读类数组,不能用 .map() 直接调用,得先转成数组;另外,如果页面里有多个 <input type="file">,但 JS 绑定的是全局 document.querySelector('input'),可能绑错元素。
立即学习“前端免费学习笔记(深入)”;
- 正确读取方式:
Array.from(event.target.files)或[...event.target.files] - 避免在
click事件里尝试读files—— 此时还没选,值为空 - 确保
input没被display: none+ 其他元素模拟点击,否则部分浏览器(如 Safari)会拒绝触发change
限制上传类型和数量,accept 和 JS 校验哪个更可靠?
accept 只是提示性过滤,用户绕过非常容易(比如改扩展名、拖拽上传)。真正可靠的校验必须在 JS 中做,尤其要检查 file.type 和 file.name,因为 file.type 可能为空(比如本地文件无 MIME 注册),此时得靠后缀判断。
批量场景下还要防数量超限:用户可能一次拖入 500 个文件,直接提交会卡死或被服务端拒收。
- 推荐组合:
accept=".pdf,.docx"+ JS 中检查files.length <= 20 - 类型校验别只信
file.type,补充file.name.toLowerCase().endsWith('.pdf') - 大文件也要提前拦:
if (file.size > 50 * 1024 * 1024) { /* 提示超限 */ }
拖拽上传批量文件时,event.dataTransfer.files 和 input.files 有什么区别?
本质一样,都是 FileList,但来源不同:前者来自拖拽区域的 drop 事件,后者来自原生 input 的 change。关键差异在于兼容性和可控性 —— dataTransfer.files 在 Firefox 中可能包含目录(需递归读取),而 input.files 永远只含文件。
拖拽批量上传最常被忽略的是 preventDefault():没在 dragover 里阻止默认行为,浏览器会直接打开文件而不是触发 drop。
- 必须在
dragover和dragenter中调用event.preventDefault() - 拖入文件夹时,Chrome / Edge 返回空
FileList,Firefox 返回items,需用item.webkitGetAsEntry()递归遍历 - 不要假设
dataTransfer.files和input.files行为完全一致 —— 它们触发时机、可访问范围、甚至长度都可能不同
批量上传真正的复杂点不在多选本身,而在后续的并发控制、进度反馈、失败重试和用户取消逻辑 —— 这些 HTML 原生不提供,得自己搭骨架。



















