必须设置enctype="multipart/form-data"且method为POST,name属性需与后端解析字段一致,accept和前端校验仅为辅助,可信校验须在后端完成,异步上传应使用FormData配合fetch且不手动设置Content-Type。

必须用 enctype="multipart/form-data",否则文件根本传不上去——这是最常被忽略、也最致命的一环。
form 标签里缺了 enctype 就等于没写上传逻辑
很多人照着示例写了个 <input type="file">,但表单的 <form> 没加 enctype="multipart/form-data",结果后端收不到文件,req.files 是空的,连日志都看不出错在哪。
-
method必须是POST,GET 不支持文件传输 -
enctype只能是"multipart/form-data",写成"application/x-www-form-urlencoded"或漏掉都会让文件数据变成空字符串 - 如果用了前端框架(比如 React)动态渲染表单,注意检查最终渲染出的
<form>标签是否真包含这个属性,别被 JSX 层级或条件渲染吃掉了
input type="file" 的 name 属性决定后端字段名
后端解析 multipart 数据时,靠的是 name 属性值来匹配文件字段。比如 Express + multer 中,upload.single('avatar') 就要求前端 <input name="avatar">,名字对不上就 400 或静默失败。
- 单文件上传:用普通字符串名,如
name="logo" - 多文件上传:建议用数组式命名,如
name="documents[]",后端更易批量处理 - 不要依赖
id或class,它们不影响提交内容 - 如果同时上传多个不同用途的文件(头像、身份证、合同),每个
<input>都要配独立的name,不能共用一个
accept 和前端校验只是辅助,不能替代后端检查
accept=".pdf,.docx" 只是浏览器层面的过滤,用户改个后缀名或用 DevTools 改 DOM 就能绕过;files[0].size 校验也只能拦住明显超限的文件,但无法防止恶意构造的超大 ZIP 或嵌套归档。
立即学习“前端免费学习笔记(深入)”;
-
accept建议按 MIME 类型写更可靠,比如accept="application/pdf,application/msword" - 前端做大小检查时,记得清空
input.value来重置控件状态:input.value = '',否则重复选同名文件可能不触发change事件 - 真正可信的校验必须在后端做:文件头检测(magic bytes)、扩展名白名单、解压深度限制、杀毒扫描(如需)
直接提交表单会跳转,异步上传要用 FormData + fetch
原生表单提交会刷新页面,现在几乎没人这么干。要用 JavaScript 拦住默认行为,把文件塞进 FormData 再发出去。
- 创建
FormData后,用append('key', file)添加文件,key必须和后端约定一致 -
fetch的body直接传FormData,**千万别手动设Content-Type头**——浏览器要自己生成boundary,设了反而破坏 multipart 结构 - 如果后端返回 JSON,记得调用
response.json(),而不是直接response.text(),否则容易把错误响应当成功处理 - 上传前检查
e.target.files.length > 0,避免用户点取消后files[0]是undefined导致脚本报错
真正卡住人的从来不是怎么写那几行 HTML,而是表单属性漏配、字段名不一致、或者误以为前端校验能防住一切——这些地方一错,后端连请求体都收不全。



















