根本原因是校验时机或方式错误:未在每次change事件中重新获取e.target.files,且formdata中文件key名不一致或大小写不同,导致后端仅接收部分文件。

为什么前端校验了 files.length 还是上传失败
根本原因不是 files.length 没读对,而是校验时机或方式不对。常见现象:用户选了 8 个文件,JS 显示“已选 5/5”,但提交后后端只收到 1 个或 0 个。这往往因为:校验只做了一次,没覆盖后续多次选择;或者清空 input.value 后没重置状态,导致 files 对象被缓存或丢失。FileList 是只读的,不能直接修改,每次 change 事件触发时都必须重新取 e.target.files,而不是依赖之前存的数组。
用 change 事件 + 累计数组控制总数量
multiple 属性只管单次多选,不限制总量。要实现“最多传 5 个”,得自己维护一个全局文件列表,并每次新增时合并、去重、截断:
- 监听
change事件,用Array.from(e.target.files)转成真数组 - 用
file.name + file.size + file.lastModified拼唯一标识,避免重复添加同一文件 - 合并进已有列表,再用
.slice(0, 5)截断,确保总数 ≤ 5 - 手动清空
input值(input.value = '')防止浏览器缓存旧选择 - 实时更新 UI 显示 “已选
currentFiles.length/5”,超限时禁用提交按钮
FormData.append 时 key 名写错导致后端只收一个
即使前端选了 5 个文件,如果往 FormData 里 append 的方式不对,后端大概率只拿到第一个。关键点就一个:所有文件必须用完全相同的 key 名调用 append:
- ✅ 正确:
formData.append('photos', file1); formData.append('photos', file2); - ❌ 错误:
formData.append('photos[0]', file1); formData.append('photos[1]', file2);—— 多数后端不认这种模拟数组的写法 - ❌ 更隐蔽的错误:
formData.append('Photos', file1); formData.append('photos', file2);—— 大小写不一致会被当两个不同字段
调试时务必打开 Network → Payload,确认每个文件是否作为独立条目出现,而不是合并成一个 blob 或只剩一项。
服务端二次校验不能省,且要防静默丢包
前端限制可被绕过,服务端必须校验 req.files?.length(Express)、$_FILES['photos']['name'] 数组长度(PHP)或 MultipartFile[] 长度(Spring Boot)。但更隐蔽的问题是:PHP 在 post_max_size 超限时会静默清空整个 $_FILES 和 $_POST,不报错也不返回 4xx。验证方式:查 PHP 错误日志,搜 POST Content-Length of XXXXX bytes exceeds the limit。必须同步调大 upload_max_filesize、post_max_size 和 memory_limit,改完后重启 PHP-FPM 和 Web 服务,再用 phpinfo() 确认生效值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











