需添加multiple属性并用Array.from转换FileList;预览用URL.createObjectURL()避免阻塞,且须手动revoke;删除时同步更新文件数组与DOM,用索引关联而非文件名。

怎么用 input[type="file"] 一次性选多个文件并生成预览列表
浏览器原生支持多文件选择,但必须显式加 multiple 属性,否则即使按住 Ctrl 点击也只返回第一个文件。选中后,input.files 是一个 FileList 对象(类数组,不可直接用 map),得转成数组再处理。
- 必须写
<input type="file" multiple accept="image/*">,accept能过滤类型、提升用户体验,但不防篡改 -
input.files每次都是新对象,不能缓存引用;想持久化得用Array.from(input.files)或展开运算符[...input.files] - 注意:Safari 16.4+ 才支持
showPicker()API,老版本只能靠click()触发原生弹窗
为什么用 URL.createObjectURL() 而不是读取 base64?
生成预览图时,直接把 File 对象转成 base64 会阻塞主线程、内存暴涨,尤其大图或批量文件。而 createObjectURL() 返回的是轻量级本地 URL 引用,浏览器内部管理资源,渲染快、无解析开销。
- 每个 URL 必须手动回收:
URL.revokeObjectURL(url),否则内存泄漏(特别是列表频繁增删时) - 该 URL 只在当前文档生命周期有效,页面刷新即失效,不能用于上传前保存或跨 iframe 传递
- 不支持直接获取文件宽高,需创建
Image实例 onload 后读取,或用URL.canParse()(较新)做基础校验
删除按钮点击后,如何同步移除对应文件和预览项?
不能只删 DOM 元素,还要从维护的文件数组里剔除对应 File,否则提交时仍会上传已“删掉”的文件。关键是靠索引或唯一标识关联 UI 和数据。
- 推荐在生成预览项时,给
<li>或容器加data-index,绑定当时数组下标;删除时按该索引 splice 数组 - 避免用
file.name做 key——重名文件、中文路径、特殊字符都可能冲突;更稳妥是用file.lastModified + file.size拼接哈希(简单场景够用) - 删除按钮事件必须阻止冒泡,否则可能意外触发外层
label的重新选择行为
IE11 或旧版 Edge 下预览失败的常见原因
这些浏览器不支持 URL.createObjectURL() 处理 File 对象(只支持 Blob),且 FileList 是只读的,无法模拟删除逻辑。
立即学习“前端免费学习笔记(深入)”;
- 降级方案:用
new FileReader().readAsDataURL(file),但必须逐个读,UI 显著卡顿 -
input.files在 IE 中无法被清空(设value = ""无效),只能重建input元素 - 不建议强行兼容——2024 年起主流项目已普遍放弃 IE 支持;若必须支持,请单独抽离 polyfill 逻辑,别混入现代代码流
真正麻烦的不是生成列表,而是删一半又加几个新文件后,如何让索引、URL 引用、原始 File 对象三者始终对齐——这里最容易漏掉 revokeObjectURL 或删错数组项。



















