应用程序/ x

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

  • 数据大小
  • 存在非ASCII字符
  • 存在于(未编码的)二进制数据上
  • 需要传输额外的数据(如文件名)
  • 我基本上没有在网上找到关于迄今为止使用不同内容类型的正式指导。


    TL; DR

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


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

    对于application/x-www-form-urlencoded ,发送到服务器的HTTP消息的主体基本上是一个巨大的查询字符串-名称/值对由符号分离( & ),以及名称从值由分离等于符号( = )。 一个例子是:

    MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

    根据规范:

    [保留]和非字母数字字符被'%HH',一个百分号和两个十六进制数字代表字符的ASCII码

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

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

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


    至少阅读第一部分!

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

    这对application/x-www-form-urlencoded没有问题,因为没有边界。 x-www-form-urlencoded也可以总是处理二进制数据,方法是将一个任意字节转换为三个7BIT字节。 效率低下,但它有效(并注意关于不能发送文件名以及二进制数据的注释不正确;您只是将它作为另一个键/值对发送)。

    multipart/form-data的问题在于,边界分隔符不能存在于文件数据中(参见RFC2388; 5.2节也包含了一个相当蹩脚的理由,因为没有适当的聚合MIME类型来避免这个问题)。

    因此,初看起来, multipart/form-data在任何文件上传,二进制或其他方面都没有任何价值。 如果你没有正确选择你的边界,那么你最终会遇到问题,不管你是发送纯文本还是原始二进制文件 - 服务器都会在错误的地方找到边界,并且你的文件将被截断,或者POST将失败。

    关键是选择一个编码和一个边界,以便您的选定边界字符不会出现在编码输出中。 一个简单的解决方案是使用base64 (不要使用原始二进制文件)。 在base64中,3个任意字节被编码为4个7位字符,其中输出字符集为[A-Za-z0-9+/=] (即字母数字或'+','/','=') 。 =是一种特殊情况,并且可能仅出现在编码输出的末尾,如单个=或双== 。 现在,选择你的边界作为一个7位ASCII字符串,它不能出现在base64输出中。 您在网络上看到的许多选择都无法通过此测试--MDN形成文档,例如,在发送二进制数据时使用“blob”作为边界 - 效果不佳。 但是,像“!blob!” 将永远不会出现在base64输出中。


    我不认为HTTP只限于POST多部分或x-www-form-urlencoded。 Content-Type Header与HTTP POST方法正交(可以填写适合您的MIME类型)。 对于典型的基于HTML表示的webapps也是这种情况(例如,json有效载荷在为Ajax请求传输有效载荷方面变得非常流行)。

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

    应用程序/ XML:

  • data-size:XML非常详细,但通常在使用压缩时并不是问题,并且认为写入访问情况(例如通过POST或PUT)比读取访问更为罕见(在很多情况下,它占所有流量的<3% )。 在那里我不得不优化写入性能的情况很少
  • 非ASCII字符的存在:您可以使用utf-8作为XML中的编码
  • 二进制数据的存在:需要使用base64编码
  • 文件名数据:你可以用XML封装这个内部字段
  • 应用程序/ JSON

  • 数据大小:比XML更紧凑,仍然是文本,但可以压缩
  • 非ASCII字符:json是utf-8
  • 二进制数据:base64(另请参阅json-binary-question)
  • 文件名数据:在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>
    
    链接地址: http://www.djcxy.com/p/499.html

    上一篇: application/x

    下一篇: HTTP Digest Authentication