enctype="multipart/form-data" 是文件上传的强制要求,必须显式设置在 form 标签上且 method 为 POST;其他编码格式无法传输二进制文件,accept 仅为前端提示,后端须校验 MIME 类型、魔数及文件大小等。
enctype="multipart/form-data" 是文件上传的强制要求,不是可选项
只要表单里有
,就必须在
标签上显式写
,且
必须为
。浏览器不会自动补全,也不接受默认值——设错或漏设,后端根本收不到文件对象(比如
或
为空)。
常见错误现象:
前端选了文件、点了提交,但后端日志里没打印出任何文件字段
用
提交,后端收到的是
字符串
用
,文件内容被 URL 编码成乱码,原始字节丢失
原因很简单:
是唯一能携带原始二进制分块(含
和边界分隔符)的编码格式;其他类型压根不支持二进制边界结构。
form 标签上写 enctype,不是 input 或 button 上
属于
的属性,只对整个表单生效。它不会因为某个
是
就自动触发,也不会继承自父级或通过 JS 动态添加后“追加生效”——必须在 HTML 渲染时就存在。
立即学习
“
前端免费学习笔记(深入)
”;
实操建议:
检查源码,确认
这一行完整存在
不要写成
,这毫无意义
如果用 JavaScript 动态创建表单,记得在
前给
元素设置
属性:
使用
+
时不用手动设
,浏览器会自动加请求头
accept 属性只是客户端提示,不能替代后端校验
能在部分浏览器中过滤文件类型选择弹窗,但它完全可被绕过:用户可以手动修改 HTML、用 curl 提交、或拖拽非允许类型文件。所以它只影响体验,不提供安全保证。
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
真正起作用的只有后端:
检查
头(如
),而非仅靠扩展名
读取文件魔数(magic bytes),比如 PNG 文件开头是
限制总请求体大小(如 Node.js 的
,Flask 的
)
重命名文件(避免
类路径遍历),用
或等效函数处理原始名
不校验 MIME 或魔数,单靠
或后缀名白名单,很容易被传入伪装的 WebShell 文件。
FormData 对象内部已隐式使用 multipart/form-data
当用 JavaScript 构造
并 append 文件时,例如:
浏览器会自动以
编码发送,且生成合法的 boundary。你不需要、也不能手动设置
请求头——一旦显式设置了,浏览器反而会禁用自动 multipart 封装,导致服务端解析失败。
容易踩的坑:
写了
→ 错误,会丢掉 boundary,后端收不到文件
把
转成 blob 再 append → 没问题,
仍能正确封装
append 普通字符串字段(如
)→ 它会和文件一起打包进同一个 multipart 请求,服务端可同时拿到文本和二进制
边界(boundary)是随机生成的,每次请求都不同,服务端解析器(如 multer、Django 的
)依赖它来切分各个 part —— 这个细节前端不用管,但得知道它真实存在且不可省略。
enctype="multipart/form-data"methodPOSTreq.filerequest.filesapplication/json[object File]application/x-www-form-urlencodedmultipart/form-dataContent-Dispositionenctypeinputtype="file"appendChildformenctypeform.enctype = "multipart/form-data"fetchFormDataenctypeContent-Type: multipart/form-data; boundary=...Content-Typeimage/jpeg89 50 4E 47multer.limits.fileSizeMAX_CONTENT_LENGTH../../etc/passwdsecure_filename()acceptFormDataconst fd = new FormData();
fd.append("avatar", fileInput.files[0]);
fetch("/upload", { method: "POST", body: fd });multipart/form-dataContent-Typeheaders: { "Content-Type": "multipart/form-data" }fileInput.files[0]FormDatafd.append("name", "Alice")request.FILES