加 multiple 属性是前提,但还需 form 的 enctype="multipart/form-data"、input 的 name="files[]"(PHP/Express 匹配)、method="POST";iOS 16.3 及更早静默忽略 multiple;读取需 Array.from(input.files);FormData 要多次 append('files', file);数量限制须 JS 实时校验并服务端二次验证。

multiple 属性必须加,否则浏览器原生只允许选一个文件——这不是 JavaScript 能绕过的限制。
为什么加了 multiple 还是只能传一个文件
大概率漏了以下至少一项硬性条件:
-
<form>标签没写enctype="multipart/form-data"—— 没这个,文件数据根本不会发出去 -
<input>的name写成name="files"而不是name="files[]"—— PHP 会覆盖,Express 的 multer 也对不上upload.array('files') - 表单
method不是POST——GET无法携带文件 - iOS Safari 16.3 及更早版本静默忽略
multiple,input.files.length永远是 1,且无报错;检测方式:navigator.userAgent.includes('iPhone') && /OS [1-9]\d?_[0-3]/.test(navigator.userAgent)
input.files 怎么安全读取不报错
input.files 是只读的 FileList,不是数组,直接调 .forEach() 会报 TypeError: not a function:
- 必须先转成真数组:
Array.from(input.files)或[...input.files] - 别用
input.value—— 它只返回第一个文件的伪造路径(如C:\fakepath\photo.jpg),对多文件毫无意义 - 每个
File对象有name、size、type、lastModified,但file.path在所有现代浏览器中都是undefined - 别
JSON.stringify(input.files)—— 结果是空对象,因为FileList不可序列化
用 FormData 上传多个文件时 append 怎么写
后端能否收到全部文件,取决于你往 FormData 里怎么填 key:
- ✅ 正确:
formData.append('files', file1); formData.append('files', file2);—— 同名多次append,后端需启用「同名多值」解析(Express 用upload.array('files'),PHP 遍历$_FILES['files']['name']数组) - ❌ 错误:
formData.append('files', input.files)—— 把整个FileList当一个值塞进去,行为不一致,Firefox 直接丢 - ❌ 错误:
formData.append('files', file1);只 append 一次 —— 大多数后端默认当单值处理,只留最后一个 - 别手动设置
Content-Type请求头 —— 浏览器会自动设为multipart/form-data并生成正确boundary - 调试时务必打开 Network 面板,看 Request Payload 里是否每个文件都作为独立条目出现,而不是合并成一个 blob
限制最多选 5 个文件,为什么不能靠 HTML 属性实现
multiple 本身不提供数量限制能力,所谓“限制”必须靠 JavaScript 实时干预:
立即学习“前端免费学习笔记(深入)”;
- 监听
change事件后立即检查input.files.length,超限时截断并提示用户 - 服务端必须二次校验 —— 前端限制可被绕过
- 别在用户选完 50 个文件后才提示“已选
input.files.length个”,应实时显示,避免误判卡死 - iOS 低版本和内存限制是真问题:iOS 16.4 以下不支持,大文件建议分块或直接走
FormData上传,别全量读进内存



















