FormData.append()传文件无效主因是未正确传入File对象或字段名不匹配,且fetch上传时手动设置Content-Type会破坏boundary导致后端收不到文件,必须由浏览器自动设置。
常见原因是直接传 File 对象但没指定字段名,或误传了 input.files[0].name 字符串而非文件对象本身。浏览器会静默忽略非法参数,控制台也不报错。
input[type="file"].f
iles[0](File 实例)作为第二个参数,不能是路径字符串或 input.value
avatar,就写 formData.append("avatar", file)
append(),或用相同字段名多次添加(如 formData.append("files", file1); formData.append("files", file2))手动设置 Content-Type 会导致浏览器无法自动插入 boundary,服务端收不到文件。这是最常踩的坑。
headers 中设 Content-Type —— fetch 会自动设为 multipart/form-data; boundary=...
fetch("/upload", {
method: "POST",
headers: { "Content-Type": "multipart/form-data" }, // ❌ 删掉这行
body: formData
});fetch("/upload", {
method: "POST",
body: formData // ✅ 让浏览器自动处理 headers
});两者都支持,但错误处理和进度监听方式不同,影响调试效率。
XMLHttpRequest 可用 upload.onprogress 监听上传进度,fetch 原生不支持(需用 ReadableStream + TransformStream 拦截,复杂度高)fetch 默认不带 cookie,如需认证,得加 credentials: "include"
XMLHttpRequest 的 responseType = "json" 会自动解析,fetch 需手动调 res.json()
前端漏掉关键属性,表单会退化为普通文本提交,FormData 也救不了。
不需要 enctype(FormData 不依赖它),但若混用原生表单提交,必须设 enctype="multipart/form-data"
必须有 name 属性,否则 input.files 虽可读取,但 FormData 构造时无法关联字段名multiple 属性: