enctype="multipart/form-data"是文件上传必需且唯一的表单编码类型,必须显式写在form标签中、配合method="post",大小写统一为小写;动态提交需用FormData构造数据,不可手动设Content-Type。

enctype="multipart/form-data" 是唯一正确值,不设或设错,文件根本不会发到后端——不是解析失败,是压根没传过去。
form 标签必须显式写 enctype="multipart/form-data"
这个属性只对 <form> 有效,写在 <input> 或 JS 里动态赋值都无效。浏览器渲染时没看到这个属性,就按默认的 application/x-www-form-urlencoded 编码,type="file" 字段直接被忽略,只留个空字符串或 C:\fakepath\xxx 路径。
- 必须和
method="post"搭配,method="get"下enctype被浏览器静默忽略 - 大小写要统一用小写:
multipart/form-data,别写成MULTIPART/FORM-DATA,虽 HTML 不区分,但易引发协作误判 - 即使表单里只有一个
<input type="file">,其他全是文本框,也得加——混合字段不改变编码要求 - 用 Vue/React 动态生成表单时,打开 DevTools 查看最终 DOM,确认
<form enctype="multipart/form-data">真实存在
JS 提交时 enctype 属性不生效,关键在 FormData
当你用 fetch() 或 XMLHttpRequest 手动发请求,<form enctype=""> 这个 HTML 属性完全被跳过。起作用的是你构造的数据对象。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- ✅ 正确做法:用
new FormData(formElement)收集数据,再传给fetch()—— 浏览器自动设Content-Type: multipart/form-data; boundary=... - ❌ 错误做法:手动拼
JSON.stringify()并设Content-Type: application/json,input.files[0]会变成[object File]字符串 - ⚠️ 注意:
FormData.append('avatar', input.files[0])的第二个参数必须是File实例,不是input.value(那是只读路径,无二进制内容) - 别手动设置
Content-Type请求头,否则浏览器会丢掉自动生成的boundary,导致后端解析失败
后端收不到文件?先盯住请求头里的 Content-Type
报错如 req.file is undefined 或 request.FILES is empty,八成不是后端代码问题,而是前端没发对。调试第一步永远是抓包。
- 打开 Chrome DevTools → Network → 找到对应请求 → Headers 标签页
- 检查
Content-Type是否为multipart/form-data; boundary=... - 如果看到
application/x-www-form-urlencoded,说明enctype没生效,或 JS 阻止了默认提交但没走FormData - 如果看到
Invalid boundary in multipart,大概率是前端手动写了Content-Type头又没填boundary
最容易被忽略的是:表单提交瞬间页面刷新或跳转,你根本看不到真实发出的请求体。不看 Network 面板里的原始请求头,光查控制台或后端日志,90% 的“上传失败”问题会绕着弯排查半天。

















