在HTTP中,POST数据有两种方式:application/x-wwww-form-urlencoded和multipart/form-data。我知道大多数浏览器只能在使用多部分/表单数据的情况下上传文件。在API上下文中何时使用其中一种编码类型(不涉及浏览器),是否有其他指导?这可能例如基于:

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

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


当前回答

至少读第一段!

我知道这已经晚了3年,但马特(被接受)的答案是不完整的,最终会让你陷入麻烦。这里的关键是,如果选择使用多部分/表单数据,则服务器最终接收的文件数据中不能出现边界。

这对于application/x-wwww-form-urlencoded来说不是问题,因为没有边界。x-www-form-urlencoded也可以通过将一个任意字节转换为三个7BIT字节的简单方法来始终处理二进制数据。效率很低,但它可以工作(请注意,关于不能发送文件名和二进制数据的评论是不正确的;您只需将其作为另一个键/值对发送)。

多部分/表单数据的问题是,文件数据中不能存在边界分隔符(请参阅RFC 2388;第5.2节还包含了一个相当蹩脚的借口,即没有适当的聚合MIME类型来避免此问题)。

因此,乍一看,多部分/表单数据在任何文件上载(二进制或其他)中都没有任何价值。如果您没有正确选择边界,那么无论您发送的是纯文本还是原始二进制文件,最终都会遇到问题-服务器将在错误的位置找到边界,文件将被截断,或者POST将失败。

关键是选择编码和边界,以使选定的边界字符不会出现在编码输出中。一个简单的解决方案是使用base64(不要使用原始二进制)。在base64中,3个任意字节被编码为4个7位字符,其中输出字符集为[A-Za-z0-9+/-=](即字母数字、“+”、“/”或“=”)。=是一种特殊情况,并且只能出现在编码输出的末尾,作为单=或双=。现在,选择边界作为7位ASCII字符串,它不能出现在base64输出中。你在网上看到的许多选择都没有通过这个测试——例如,MDN表单文档在发送二进制数据时使用“blob”作为边界——这是不好的。然而,类似“!blob!”的内容永远不会出现在base64输出中。

其他回答

我同意曼努埃尔所说的很多话。事实上,他的评论是指这个url。。。

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

…其中指出:

内容类型“application/x-wwww-form-urlencoded”是发送大型邮件时效率低下二进制数据或文本的数量包含非ASCII字符。这个内容类型“多部分/表单数据”应用于提交表格包含文件、非ASCII数据、,和二进制数据。

然而,对我来说,这取决于工具/框架支持。

您使用哪些工具和框架期望您的API用户正在构建他们的应用程序?他们有吗他们可以使用的框架或组件这种方法比另外

如果你清楚地了解你的用户,以及他们将如何使用你的API,那么这将有助于你做出决定。如果你让你的API用户很难上传文件,那么他们就会离开,你会花很多时间来支持他们。

其次是您编写API的工具支持,以及如何轻松地适应一种上传机制。

我认为HTTP不限于多部分或x-www-form-urlencoded的POST。Content-TypeHeader与HTTPPOST方法正交(您可以填写适合您的MIME类型)。这也是典型的基于HTML表示的Web应用程序的情况(例如,json有效负载对于传输ajax请求的有效负载变得非常流行)。

关于HTTP上的Restful API,我接触到的最流行的内容类型是application/xml和application/json。

应用程序/xml:

数据大小:XML非常冗长,但在使用压缩时通常不会出现问题,并且认为写访问情况(例如通过POST或PUT)比读访问更罕见(在许多情况下,它小于所有流量的3%)。很少有我必须优化写性能的情况存在非ascii字符:可以使用utf-8作为XML编码二进制数据的存在:需要使用base64编码文件名数据:可以在XML中封装此内部字段

应用程序/json

数据大小:比XML更紧凑,仍然是文本,但可以压缩非ascii字符:json是utf-8二进制数据:base64(另见json二进制问题)文件名数据:封装为json中自己的字段部分

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

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

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>

如果需要使用Content-Type=x-www-urlencoded-form,则不要将FormDataCollection用作参数:在asp.net Core 2+中,FormDataCollection没有格式化程序所需的默认构造函数。请改用IFormCollection:

 public IActionResult Search([FromForm]IFormCollection type)
    {
        return Ok();
    }

至少读第一段!

我知道这已经晚了3年,但马特(被接受)的答案是不完整的,最终会让你陷入麻烦。这里的关键是,如果选择使用多部分/表单数据,则服务器最终接收的文件数据中不能出现边界。

这对于application/x-wwww-form-urlencoded来说不是问题,因为没有边界。x-www-form-urlencoded也可以通过将一个任意字节转换为三个7BIT字节的简单方法来始终处理二进制数据。效率很低,但它可以工作(请注意,关于不能发送文件名和二进制数据的评论是不正确的;您只需将其作为另一个键/值对发送)。

多部分/表单数据的问题是,文件数据中不能存在边界分隔符(请参阅RFC 2388;第5.2节还包含了一个相当蹩脚的借口,即没有适当的聚合MIME类型来避免此问题)。

因此,乍一看,多部分/表单数据在任何文件上载(二进制或其他)中都没有任何价值。如果您没有正确选择边界,那么无论您发送的是纯文本还是原始二进制文件,最终都会遇到问题-服务器将在错误的位置找到边界,文件将被截断,或者POST将失败。

关键是选择编码和边界,以使选定的边界字符不会出现在编码输出中。一个简单的解决方案是使用base64(不要使用原始二进制)。在base64中,3个任意字节被编码为4个7位字符,其中输出字符集为[A-Za-z0-9+/-=](即字母数字、“+”、“/”或“=”)。=是一种特殊情况,并且只能出现在编码输出的末尾,作为单=或双=。现在,选择边界作为7位ASCII字符串,它不能出现在base64输出中。你在网上看到的许多选择都没有通过这个测试——例如,MDN表单文档在发送二进制数据时使用“blob”作为边界——这是不好的。然而,类似“!blob!”的内容永远不会出现在base64输出中。

只是我这边上传HTML5画布图像数据的一点提示:

我正在为一家印刷店做项目,由于将来自HTML5画布元素的图像上传到服务器,我遇到了一些问题。我挣扎了至少一个小时,但我无法在服务器上正确保存图像。

一旦我设置了jQuery ajax调用application/x-wwww-form-urlencoded的contentType选项一切都正确,base64编码的数据被正确解释并成功保存为图像。


也许这对某人有帮助!