表单上传文件必须设置enctype="multipart/form-data",input type="file"需带name属性,后端须启用multipart解析并严格校验文件大小、类型及重命名防攻击。

form 必须设置 enctype="multipart/form-data"
浏览器默认用 application/x-www-form-urlencoded 编码表单,这种编码会把文件内容转成 URL 安全字符串,彻底破坏二进制数据。不设对 enctype,后端收不到原始文件——连空文件都收不到。
正确写法只有这一种:
<form method="POST" enctype="multipart/form-data">。别用
text/plain,也别漏掉 enctype 属性(此时浏览器会回退到默认编码)。
input type="file" 要加 name 属性才可提交
没 name 的 <input type="file"> 不会出现在表单数据里,后端根本看不到这个字段。常见错误是只写 <input type="file" id="avatar">,却忘了加 name="avatar"。
- 单文件上传:用
<input type="file" name="photo"> - 多文件:加
multiple,如<input type="file" name="attachments" multiple>,后端收到的是文件列表 - 限制类型:用
accept="image/*,.pdf",但只是前端提示,不可替代后端校验
后端接收时注意 multipart 解析是否启用
很多轻量框架(如 Express、Flask 默认配置、FastAPI 默认)不自动解析 multipart/form-data。你看到 req.body 是空的,或者整个请求体是一长串乱码,大概率是没配解析中间件。
立即学习“前端免费学习笔记(深入)”;
- Express:必须加
multer或busboy,body-parser对文件完全无效 - Flask:用
request.files,不是request.form;且确保没禁用MAX_CONTENT_LENGTH - PHP:直接读
$_FILES数组,但要注意upload_max_filesize和post_max_size的 php.ini 限制
别忽略文件大小和类型校验的双重防线
accept 和 max 属性(如 <input type="file" accept="image/jpeg" max="2097152">)只能防误操作,不能防绕过。用户改 HTML、用 curl、写脚本都能跳过这些限制。
真正起作用的只有后端校验:
- 检查
Content-Length头或流式读取时的累计字节数,防止超大文件耗尽内存 - 读文件头(magic bytes),而不是只看扩展名或
Content-Type,因为后者容易伪造 - 临时文件保存前务必重命名,避免路径遍历(如传
../../../etc/passwd)
前端限制松一点没关系,后端限制漏一点就可能出事。



















