http - 使用application/x-www-form-urlencoded还是multipart/form-data?

  显示原文与译文双语对照的内容

在HTTP中,有两种发布数据的方法: application/x-www-form-urlencodedmultipart/form-data 。我明白大多数浏览器只有使用 multipart/form-data 才能上传文件。 在API上下文中使用一种编码类型时是否还有其他的指导? 这可能基于:

  • 数据大小
  • non-ASCII字符的存在
  • ( 未编码) 二进制数据上的存在
  • 需要传输额外数据( 比如文件名)

我基本上没有在网上找到关于使用不同content-types的正式指南。

时间:

我不认为HTTP只能在多部分或者x-www-form-urlencoded中发布。 Content-Type 标题 。is与 HTTP POST 方法( 你可以填充适合你的MIME类型) 正交。 这也是典型的基于HTML表示的web应用程序( 例如。 json负载在传输ajax请求负载时变得非常流行。

关于基于HTTP的Restful API,最流行的content-types我接触的是应用程序/xml和应用程序/json 。

应用程序/xml:

  • data-size: XML非常冗长,但在使用压缩和考虑写入访问情况时通常不是问题( 例如。 通过POST或者放置,更罕见的是 read-access ( 在很多情况下,它是所有流量的<3% ) 。 在那里我很少需要优化写性能
  • non-ascii字符的存在:你可以使用utf-8作为XML编码
  • 二进制数据的存在:需要使用base64编码
  • 文件名数据:你可以将这里字段封装在XML中

应用程序/json

  • data-size: 更紧凑的XML,仍然是文本,但你可以压缩
  • non-ascii字符:json是 utf-8
  • 二进制数据:base64 ( 也见于 json-binary-question )
  • 文件名数据:在json内封装为自己的field-section

二进制数据作为自己的资源

我将尝试将二进制数据表示为自己的资产/资源。 它添加了另一个调用,但会更好地分离内容。 示例图像:


POST/images
Content-type: multipart/mixed; boundary="xxxx" 
... multipart data

201 Created
Location: http://imageserver.org/../foo.jpg
 

在以后的资源中,你可以简单地将二进制资源作为链接内联:


<main-resource>
.. .
 <link href="http://imageserver.org/../foo.jpg"/>
</main-resource>

在这里至少阅读了

我知道这已经是 3年了,但是( 接受)的答案是不完整的,最终会让你陷入麻烦。 这里的关键是,如果你选择使用 multipart/form-data,那么在服务器最终接收到的文件数据中,边界必须 。

对于 application/x-www-form-urlencoded 来说,这不是一个问题,因为没有边界。 x-www-form-urlencoded 也可以总是处理二进制数据,通过简单地将一个任意字节转换成三个 7BIT 字节。 低效,但它可以运行( 请注意,关于不能够发送文件名和二进制数据的注释不正确;你只需将它作为另一个键/值对发送) 。

multipart/form-data的问题是,边界分隔符不能出现在文件数据( 参见 RFC2388 ;第 5.2节还提供了一个相当蹩脚的借口,用于不使用适当的聚合MIME类型,从而避免这个问题) 中。

因此,乍一看, multipart/form-data 没有任何价值的任何文件上传,二进制或其他。 如果你不选择你正确边界,然后你最终会有一个问题,你是否发送纯文本或原始二进制,服务器将找到一个边界在错误的地方,和你的文件将被截断,或者邮局就会失败。

关键是选择一个编码和一个边界,这样你所选的边界字符就不能出现在编码输出中。 一个简单的解决方案是使用 base64 ( 不使用原始二进制) 。 在 base64 3中,任意字节编码为4 7个-bit字符,其中输出字符集为 [A-Za-z0-9+/=] ( IE ) 。 字母数字,或者'+','/','=') 。 = 是一个特例,并且只能出现在编码输出的末尾,作为单个 = 或者双 == 。 现在,选择你的边界作为 7 -bit ASCII字符串,它不能出现在 base64 输出中。 很多选择在网上你看到这个测试失败——mdn docs形式,例如,使用"blob"边界当发送二进制数据,而不是好。 但是,像"blob"这样的东西永远不会出现在 base64 输出中。

...