multiple属性仅允许多选文件,不自动展示列表;需用JavaScript遍历input.files渲染文件名、大小等,并用FileReader预览内容;FileList只读不可删减,应维护独立数组管理已选文件。

multiple 属性本身不控制文件列表展示逻辑
HTML 的 <input type="file"> 加上 multiple 只是允许用户一次选多个文件,它不会自动帮你生成文件名列表、预览或删除按钮。浏览器只在表单提交时把所有选中的文件一并发出,input.files 是一个 FileList 对象,得你自己读取、渲染、管理。
常见错误现象:加了 multiple 后页面没反应,以为“应该自动显示文件”,结果发现 DOM 里只有个空 input;或者监听了 change,但只取了 e.target.files[0],漏掉其余文件。
- 务必用
e.target.files(不是e.dataTransfer.files,除非你做了拖拽) -
FileList是只读类数组,不能用.push()或.splice()修改 - IE10–11 支持
multiple,但不支持FileList.forEach,需用for循环
用 JavaScript 读取并渲染文件名与大小
用户选完后,你需要遍历 input.files,提取 name 和 size,再插入到页面中。注意单位换算和可读性——直接显示字节数没人看得懂。
示例逻辑:
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
const input = document.querySelector('input[type="file"][multiple]');
input.addEventListener('change', () => {
const files = Array.from(input.files); // 转成真数组,方便 map/filter
const listHtml = files.map(f =>
`<div><code>${f.name}</code> (${(f.size / 1024).toFixed(1)} KB)</div>`
).join('');
document.getElementById('file-list').innerHTML = listHtml;
});
- 别用
files.length === 0判断是否清空——用户可能取消选择,此时files是空FileList,但事件仍会触发 - 避免直接拼接 HTML 渲染大量文件(比如上百个),考虑用
document.createDocumentFragment提升性能 -
f.lastModified可读取时间戳,但格式需手动转成可读字符串(如new Date(f.lastModified).toLocaleString())
文件对象不能直接预览内容,需 FileReader 配合
如果要显示图片缩略图、文本内容或 PDF 封面,File 对象本身只是引用,必须用 FileReader 异步读取。每个文件都要单独实例化一个 FileReader,且不能复用。
常见错误:在一个循环里反复赋值同一个 reader.onload,结果所有回调都只反映最后一个文件的内容——因为闭包捕获的是循环变量的最终值。
- 正确做法是用
let声明循环变量,或用立即执行函数包裹reader实例 - 图片建议用
readAsDataURL,文本用readAsText(注意指定编码,如readAsText(file, 'UTF-8')) - 大文件(>50MB)读取可能卡 UI,可加 loading 状态或限制文件类型/大小
删除某个已选文件需要重新构造 FileList(实际不可行)
这是最容易被忽略的复杂点:FileList 是只读且不可变的。你无法从里面删掉某一项,也不能通过设置 input.files = newFileList 来更新——这个属性是只读的,赋值无效(Chrome 会静默忽略,Firefox 报错)。
所以“删除已选文件”只能靠模拟:把用户选中的文件存进一个 JS 数组(如 selectedFiles = []),每次添加时 push,删除时 filter,上传时传这个数组给 FormData。
- 不要依赖
input.files作为唯一数据源,它只适合一次性读取 - 重置 input(
input.value = '')会清空整个列表,无法局部删除 - 如果用了拖拽上传,
dataTransfer.files同样不可变,处理逻辑一致


















