单个 input 无法同时选封面和多图,需用两个 input:name="cover" 传单张封面,name="photos[]" 传多张内容图;js 上传时需遍历 photofiles 逐个 append('photos', photo),不可合并或错命名。

直接用 <input type="file"> + FormData 就能实现,关键不是“怎么搭”,而是“字段怎么命名”和“多图怎么传不丢”。
如何让单个 input 同时选封面和多张照片
HTML 层面必须区分两个逻辑:一个封面(单文件),一组内容图(多文件)。不能全塞进同一个 name 里,否则后端收不到结构化数据。
-
<input type="file" name="cover" accept="image/*">—— 封面,只允许选 1 张 -
<input type="file" name="photos[]" multiple accept="image/*">—— 照片组,[]是 PHP 的数组语法;Node.js/Express 用multer时也认这个命名习惯 - 别漏掉
enctype="multipart/form-data",表单没它,文件字段直接变空字符串
为什么 fetch 上传后端收不到 photos[]
常见错在 JS 层把多个 File 对象当成一个整体 append,但后端解析依赖字段名和顺序。正确做法是遍历 files 列表,逐个 append,且用相同字段名:
const formData = new FormData();
formData.append('cover', coverFile); // 封面
for (const photo of photoFiles) {
formData.append('photos', photo); // 注意:这里用 'photos',不是 'photos[]'
}
——后端看到多个同名字段 photos,就会自动聚合成数组(PHP 自动转成 $_FILES['photos'] 数组;Express + multer 配 array('photos') 即可)。
- 手动设
Content-Type头?绝对不行,fetch会覆盖 boundary,导致 400 - 用
event.target.files拿到的是FileList,不是数组,得用Array.from()或for...of遍历
用户点“拍照”却上传失败?检查 capture 和 accept 组合
移动端调起相机靠 capture="camera",但它和 accept 冲突时可能失效:
-
accept="image/*"+capture="camera"✅ 大多数安卓可行 -
accept="image/jpeg,image/png"+capture="camera"❌ iOS Safari 常静默失败(只认image/*) - 不要对
input用display: none,改用opacity: 0+ 绝对定位盖在按钮上,否则 iOS 不响应click()
上传前必须做的三件事
别等后端报错才补救,前端拦截能省大量调试时间:
- 检查
file.size > 20 * 1024 * 1024(20MB),超了直接alert并return - 检查
file.type.startsWith('image/'),避免用户绕过accept选了 .exe - 预览封面图用
FileReader,但别对所有photos[]都读取——大图多张会卡顿,只读缩略图 URL:URL.createObjectURL(file)
最易被忽略的点:后端接收到的 photos 字段名必须和 formData.append('photos', ...) 完全一致,大小写、下划线、中括号一个都不能错;Node.js 默认不解析 photos[] 这种带方括号的字段名,得靠中间件显式配置。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











