一尘不染

应用程序/x-www-form-urlencoded 还是 multipart/form-data?

javascript

在 HTTP 中有两种 POST 数据的方式:application/x-www-form-urlencodedmultipart/form-data. 我了解大多数浏览器只有在使用时才能上传文件multipart/form-data。在 API 上下文(不涉及浏览器)中使用其中一种编码类型时是否有任何其他指导?这可能例如基于:

  • 数据大小
  • 非 ASCII 字符的存在
  • 存在于(未编码的)二进制数据上
  • 需要传输其他数据(如文件名)

到目前为止,我基本上没有在网上找到关于使用不同内容类型的正式指南。


阅读 129

收藏
2022-02-23

共1个答案

一尘不染

概括; 如果您有二进制(非字母数字)数据(或相当大的有效载荷)要传输,请使用multipart/form-data. 否则,使用application/x-www-form-urlencoded.


Content-Type您提到的 MIME 类型是用户代理(浏览器)必须支持的 HTTP POST 请求的两个标头。这两种类型的请求的目的都是向服务器发送名称/值对列表。根据所传输数据的类型和数量,其中一种方法将比另一种更有效。要了解原因,您必须查看每个人在幕后所做的事情。

因为application/x-www-form-urlencoded,发送到服务器的 HTTP 消息的主体本质上是一个巨大的查询字符串——名称/值对由 & 号 ( &) 分隔,名称与值由等号 ( =) 分隔。这方面的一个例子是:

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

根据规范

[保留和] 非字母数字字符替换为 `%HH’、一个百分号和两个表示字符 ASCII 码的十六进制数字

这意味着对于我们的一个值中存在的每个非字母数字字节,将需要三个字节来表示它。对于大型二进制文件,将有效负载增加三倍将非常低效。

这就是multipart/form-data进来的地方。使用这种传输名称/值对的方法,每对都表示为 MIME 消息中的“部分”(如其他答案所述)。部分由特定的字符串边界分隔(特别选择以便此边界字符串不会出现在任何“值”有效负载中)。每个部分都有自己的一组 MIME 标头,例如Content-Type,特别是Content-Disposition,它们可以为每个部分提供其“名称”。每个名称/值对的值片段是 MIME 消息每个部分的有效负载。MIME 规范在表示值有效负载时为我们提供了更多选择——我们可以选择更有效的二进制数据编码来节省带宽(例如 base 64 甚至原始二进制)。

为什么不multipart/form-data一直使用?对于较短的字母数字值(如大多数 Web 表单),添加所有 MIME 标头的开销将大大超过更有效的二进制编码所节省的成本。

2022-02-23