HTML 表单 enctype 怎么选?urlencoded 和 multipart 区别

chinaz
chinaz 初级会员超兽战士
发布于 2026-10-08 15:05 ·1 浏览 ·0 回复

结论:表单里有 <input type="file"> 就必须用 enctype="multipart/form-data";纯文本字段直接用默认的 application/x-www-form-urlencoded 即可;text/plain 只在调试时用,生产环境不要碰。另外记住一点:enctype 只在 method="post" 时生效。

enctype 是什么?什么时候才生效?

enctype(encoding type)是 <form> 标签的属性,用来指定浏览器把表单数据打包成请求体时使用的编码格式。它只有三个合法值:application/x-www-form-urlencoded(默认值)、multipart/form-data、text/plain。

关键点是:当 method="get" 时,表单数据会拼进 URL 的查询串,根本没有请求体,enctype 完全不起作用。HTML 规范明确要求 method="get" 时 enctype 必须是 application/x-www-form-urlencoded,你写 multipart/form-data 浏览器也会忽略。

所以第一个决策条件是:先看你的表单是不是 POST。

urlencoded 和 multipart/form-data 有什么区别?

结论:两者的本质差别是"文本编码"和"二进制封装"——urlencoded 把每个字节做百分号转义后拼成一行字符串,multipart 把每个字段切成独立区块原样传输。

application/x-www-form-urlencoded 的格式是 name=value&name2=value2。所有非 ASCII 字符先按 UTF-8 编码,再逐字节转成 %XX,空格转成 +,&、=、+ 要转义成 %26、%3D、%2B。代价是:一个非 ASCII 字节要占 3 个字符,二进制数据的体积平均膨胀 2~3 倍,1MB 的图片会撑成 2MB 以上的请求体。

multipart/form-data 的格式是用一个随机 boundary(边界字符串)把各字段隔开,每个部分带自己的 Content-Disposition: form-data; name="xxx",文件字段还带 filename 和 Content-Type。二进制数据不做任何编码,体积等于原始大小,每部分只多几十到一百多字节的头部开销。

用 urlencoded 提交文件会怎样?

结论:文件内容根本不会上传,服务器只能拿到一个文件名字符串。

<input type="file"> 在 urlencoded 模式下,提交的是它的 value,也就是用户选中的文件名(如 photo.jpg),字节内容被丢弃。后端既拿不到流,也写不出文件。所以在 PHP 里,$_FILES 只有在 multipart/form-data 时才非空;urlencoded 提交时 $_FILES 是空数组,文件名混在 $_POST 里。

fetch / axios 传 FormData 还需要手动设 enctype 吗?

结论:不需要,也千万不要手动设 Content-Type。

用 FormData 时,浏览器或运行时会自动生成 boundary 并设置完整的 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXXXX。如果你手写 headers: {'Content-Type': 'multipart/form-data'},boundary 就丢了,后端解析会直接失败。axios 传 FormData 同理,不要配 header,让它自己判断。

text/plain 为什么不能用?

结论:它只是给人看的调试格式,后端框架不解析它。

text/plain 的格式是每行一个 name=value,不做任何转义。如果值里出现换行符,结构当场崩掉。PHP 不会把它的内容放进 $_POST,Java、Node 的主流 body parser 也默认不处理。唯一用途是打开浏览器 DevTools 看一眼原始结构。

实际项目里怎么选?

按这个顺序判断即可:

  1. 表单含 <input type="file"> → enctype="multipart/form-data";
  2. 全是文本字段 → 什么都不写,用默认的 urlencoded;
  3. 用 GET 提交 → 不用管 enctype;
  4. 永不使用 text/plain。

最后别忘了服务端体积限制:Nginx 的 client_max_body_size 默认是 1m,PHP 的 post_max_size 默认 8M、upload_max_filesize 默认 2M。超过这些值会返回 413 或让 $_POST/$_FILES 变空,这跟 enctype 选错的表现很像,排查时一起看。用 curl 测试时记住:-d 发的是 urlencoded,-F 发的才是 multipart。

版权声明:本文来自 GJ站长论坛《HTML 表单 enctype 怎么选?urlencoded 和 multipart 区别》
原文链接:https://www.gj0.com/thread-1019.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~