必须添加 multiple 属性才能一次性选多张图片,否则即使 ctrl/cmd 多选也只提交最后一张;accept="image/*" 仅前端过滤,后端须校验;旧版 safari 需 js 模拟;filelist 非数组,需转为 array 处理;后端需适配多文件解析(如 multer.array);预览用 url.createobjecturl 并及时 revoke;ios 图片旋转需 canvas 修正 exif 方向;android 压缩问题可尝试 capture="environment"。

如何用 <input type="file"> 一次性选多个图片
必须加 multiple 属性,否则浏览器只允许选 1 张。不加这个属性,哪怕用户按住 Ctrl 或 Cmd 多选,表单也只提交最后一张。
常见错误写法:<input type="file" name="images"> —— 这样永远只传 1 张。
正确写法示例:
<input type="file" name="images" accept="image/*" multiple>
-
accept="image/*"能过滤非图片类型(但只是前端提示,后端仍需校验) - 部分旧版 Safari 不支持
multiple,如需兼容 iOS 12 以下,得用多个单文件 input + JS 模拟 - 选中的文件会以
FileList形式存在input.files中,不是普通数组,不能直接用map或forEach
后端接收时为什么只拿到 1 张或报错
多数后端框架(如 Express、Django、Flask)默认不自动解析多文件同名字段。比如 name="images" 提交了 3 张图,但后端只收到第 1 张,或整个字段被当成字符串丢弃。
关键点在于:表单 enctype 必须是 multipart/form-data,且后端中间件/库要支持数组式文件解析。
- Express +
multer:要用upload.array('images'),不是upload.single() - Django:用
request.FILES.getlist('images'),不是request.FILES['images'] - PHP:
$_FILES['images']['name']是数组,需遍历$_FILES['images']['tmp_name']等对应键 - 若用 fetch 提交,不能直接传 FormData 给
JSON.stringify,会丢文件
用 JavaScript 动态预览多图并控制上传顺序
用户选完图后,想立刻看到缩略图,并允许拖拽排序或删除某张——这得靠 FileReader 和手动管理 input.files 的副本。
注意:input.files 是只读的 FileList,无法增删改;要实现“删除某张再上传”,得自己维护一个 Array<file></file> 数组,最后用 FormData.append('images', file) 循环添加。
- 预览每张图前,先用
URL.createObjectURL(file)生成临时 URL,避免 FileReader 同步阻塞 - 不要在循环里反复调用
createObjectURL后不revoke,内存会泄漏 - 如果用户重复选择同一张图,
input.files的lastModified可能相同,需用file.name + file.size做简易去重
移动端拍照上传图片模糊或旋转异常
iOS Safari 拍照后上传,常出现图片被旋转 90° 或压缩严重。这不是表单问题,而是原图含 EXIF 朝向信息,且部分浏览器上传前自动转码。
解决方案不是改表单,而是上传前用 canvas 读取并修正 orientation:
- 用
exif-js或原生fetch读取图片二进制头,解析Orientationtag - 用 canvas 绘制时根据 orientation 做 rotate/scale,再
canvas.toBlob得到修正后文件 - Android 部分厂商浏览器(如华为、小米)会强制压缩 >2MB 的图片,需在
accept加capture="environment"显式调用后置摄像头,有时能绕过压缩
真正麻烦的是:这些处理都得在用户点击“提交”前完成,而不是依赖后端修复。表单本身只管把 File 对象交出去,图像质量、方向、尺寸全得前端兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











