application/x-www-form-urlencoded 还是 multipart/form-data?
application/x-www-form-urlencoded 还是 multipart/form-data?
技术背景
在 HTTP POST 请求中,application/x-www-form-urlencoded
和 multipart/form-data
是用户代理(如浏览器)必须支持的两种 Content-Type
头部。这两种请求类型的目的都是向服务器发送一组名值对,不过根据传输数据的类型和数量,其中一种方法会比另一种更高效。
实现步骤
application/x-www-form-urlencoded
- HTTP 消息体本质上是一个巨大的查询字符串,名值对之间用
&
分隔,名称和值之间用=
分隔。 - 非字母数字字符会被替换为
%HH
(HH
是代表字符 ASCII 码的两位十六进制数字)。 - 示例:
MyVariableOne=ValueOne&MyVariableTwo=ValueTwo
multipart/form-data
- 每个名值对在 MIME 消息中表示为一个“部分”,部分之间由特定的字符串边界分隔。
- 每个部分都有自己的 MIME 头部,如
Content-Type
和Content-Disposition
,后者可以为每个部分命名。 - 名值对的值部分是 MIME 消息每个部分的有效负载,可以选择更高效的二进制数据编码方式(如 Base64 或原始二进制)以节省带宽。
核心代码
使用 application/x-www-form-urlencoded
的示例(JavaScript)
1 |
|
使用 multipart/form-data
的示例(JavaScript)
1 |
|
最佳实践
- 如果要传输二进制(非字母数字)数据或大量有效负载,使用
multipart/form-data
。 - 如果是短字母数字值(如大多数 Web 表单),使用
application/x-www-form-urlencoded
。 - 当使用
multipart/form-data
时,选择的边界字符不能出现在编码输出中,例如可以使用 Base64 编码,并选择一个不会出现在 Base64 输出中的 7 位 ASCII 字符串作为边界。
常见问题
application/x-www-form-urlencoded
的问题
对于大的二进制文件,由于每个非字母数字字节需要用三个字节来表示,会导致有效负载大幅增加,效率低下。
multipart/form-data
的问题
边界分隔符不能出现在文件数据中,否则服务器可能会在错误的位置找到边界,导致文件截断或 POST 请求失败。因此,需要选择合适的编码和边界。
其他问题
- 在使用
Content-Type=x-www-urlencoded-form
时,在 ASP.NET Core 2+ 中不要使用FormDataCollection
作为参数,应使用IFormCollection
。 - 当响应的
contentType
是application/x-www-form-urlencoded
但实际包含 JSON 数据时,在 Django 中访问request.data
可能无法正确转换,需要访问request.body
。
application/x-www-form-urlencoded 还是 multipart/form-data?
https://119291.xyz/posts/application-x-www-form-urlencoded-or-multipart-form-data/