• post请求头中常见content-type(非常重要)


    定义和用法

    enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码
    默认地,表单数据会编码为 "application/x-www-form-urlencoded"。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。

     

    enctype属性值

     

    描述
    application/x-www-form-urlencoded 在发送前编码所有字符(默认)
    multipart/form-data

    不对字符编码。

    在使用包含文件上传控件的表单时,必须使用该值。

    text/plain 空格转换为 "+" 加号,但不对特殊字符编码。

     

     

    HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。
    其中 POST 一般用来向服务端提交数据,本文主要讨论 POST 提交数据的几种方式。

     

    我们知道,HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。
    规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。类似于下面这样:

     

    BASH<method> <request-URL> <version>
    <headers>
    
    <entity-body>
    

     

    协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

     

    但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。
    服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。
    所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。
    下面就正式开始介绍它们。

     

    application/x-www-form-urlencoded

     

    这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。

     

    <form action="form_action.asp" enctype="text/plain">
      <p>First name: <input type="text" name="fname" /></p>
      <p>Last name: <input type="text" name="lname" /></p>
      <input type="submit" value="Submit" />
    </form>

     

    此时Form提交的请求数据,抓包时看到的请求会是这样的内容(无关的请求头在本文中都省略掉了):

     

    BASHPOST http://www.example.com HTTP/1.1
       Content-Type: application/x-www-form-urlencoded;charset=utf-8
       title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

     

    首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。
    大部分服务端语言都对这种方式有很好的支持。例如 PHP 中,$_POST['title'] 可以获取到 title 的值,$_POST['sub'] 可以得到 sub 数组。

     

    很多时候,我们用 Ajax 提交数据时,也是使用这种方式。
    例如 JQuery 和 QWrap 的 Ajax,Content-Type 默认值都是「application/x-www-form-urlencoded;charset=utf-8」。

     

    multipart/form-data

     

    这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的enctype 等于 multipart/form-data。直接来看一个请求示例:

     

    BASHPOST http://www.example.com HTTP/1.1
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    Content-Disposition: form-data; name="text"
    
    title
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    Content-Disposition: form-data; name="file"; filename="chrome.png"
    Content-Type: image/png
    
    PNG ... content of chrome.png ...
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
    

     

    这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。
    关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。

     

    这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

     

    上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。

     

    随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

     

    application/json

     

    application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

     

    JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

     

    Google 的 AngularJS 中的 Ajax 功能,默认就是提交 JSON 字符串。例如下面这段代码:

     

    JSvar data = {'title':'test', 'sub' : [1,2,3]};
    $http.post(url, data).success(function(result) {
        ...
    });

     

     

    最终发送的请求是:

     

    BASHPOST http://www.example.com HTTP/1.1 
    Content-Type: application/json;charset=utf-8
    
    {"title":"test","sub":[1,2,3]}

     

     

    这种方案,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler,都会以树形结构展示 JSON 数据,非常友好。但也有些服务端语言还没有支持这种方式,例如 php 就无法通过 $_POST 对象从上面的请求中获得内容。这时候,需要自己动手处理下:在请求头中 Content-Type 为 application/json 时,从 php://input 里获得原始输入流,再 json_decode 成对象。一些 php 框架已经开始这么做了。

     

    当然 AngularJS 也可以配置为使用 x-www-form-urlencoded 方式提交数据。如有需要,可以参考这篇文章

     

    text/xml

     

    我的博客之前提到过 XML-RPC(XML Remote Procedure Call)。它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。典型的 XML-RPC 请求是这样的:

     

    复制代码
    HTMLPOST http://www.example.com HTTP/1.1 
    Content-Type: text/xml
    
    <?xml version="1.0"?>
    <methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
            <param>
                <value><i4>41</i4></value>
            </param>
        </params>
    </methodCall>
    复制代码

     

    XML-RPC 协议简单、功能够用,各种语言的实现都有。它的使用也很广泛,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服务等等。JavaScript 中,也有现成的库支持以这种方式进行数据交互,能很好的支持已有的 XML-RPC 服务。不过,我个人觉得 XML 结构还是过于臃肿,一般场景用 JSON 会更灵活方便。

     

    https://imququ.com/post/four-ways-to-post-data-in-http.html

     

    rest api参数与content-type

     

    最近为项目组提供rest api 时遇到了关于接口参数的传递问题,主要是没有充分考虑到第三方调用者的使用方式,应该尽量的去兼容公司之前提供出去的接口调用方式,这样可以降低第三方调用者的学习成本,尽管之前的方式并不是那么的推荐,好的做法是即兼容老的做法也支持推荐的做法。

    对于基于http post接口,Content-type我会优先选择application/json,但公司之前提供的接口恰恰采用了application/x-www-form-urlencoded,它是表单默认的提交类型,基于key/value形式提交到服务端的。
    spring mvc是如何接收下面两种经典数据的? (至于form-data,它即可以传键值对也可以上传文件,这里不涉及到文件所以只讨论下面两种):

    • Content-type=application/json:需要在参数上增加@RequestBody这个注解,说明参数是从http的requestbody中获取。

    下图中的参数,是标准的json格式,对前端js非常友好。

    • Content-type=application/x-www-form-urlencoded,参数上不能增加@RequestBody的注解

    下图的可以看出参数形式与get请求时,URL后面的参数格式


    为什么不推荐采用application/x-www-form-urlencoded这种类型,它有如下问题:

    • 测试困难,就别想通过postman这类工具测试:提交到服务端实际上是一个MultiValueMap(org.springframework.util.MultiValueMap或org.springframework.util.LinkedMultiValueMap),
      如果value中的对象也是一个对象,那么在构建这个参数时就非常困难,看下它的过程
      • 采用key1=value1&key2=value2这种形式将所有参数拼接起来,从一长串字符中想了解每个参数的含义没有个好眼力怕是不行。
      • value要进行编码,编码之后的对调试者不友好。
      • value是复杂对象的情况更加糟糕,一般只能通过程序来序列化得到参数,想手写基本不可能。
    • 客户端调用复杂
     

    新版本Postman在此处查看:


    2、x-www-form-urlencoded:
    就是application/x-www-from-urlencoded,会将表单内的数据转换为键值对,比如,name=java&age = 23

    3、raw
    可以上传任意格式的文本,可以上传text、json、xml、html等


    4、binary
    相当于Content-Type:application/octet-stream,从字面意思得知,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件。


    multipart/form-data与x-www-form-urlencoded区别
    multipart/form-data:既可以上传文件等二进制数据,也可以上传表单键值对,只是最后会转化为一条信息;
    x-www-form-urlencoded:只能上传键值对,并且键值对都是间隔分开的。

    http://blog.csdn.net/ye1992/article/details/49998511
     

    上传文件的表单中<form>要加属性enctype="multipart/form-data",很多人只是死记硬背知道上传表单要这么 写,知其然而不知其所以然。那到底为什么要添加这个属性呢?它是什么意思呢?它又有什么其他可选值呢? 其实form表单在你不写enctype属性时,也默认为其添加了enctype属性值,默认值是enctype="application/x- www-form-urlencoded".这个属性管理的是表单的MIME编码,共有三个值可选:
      ①application/x-www-form-urlencoded (默认值)
      ②multipart/form-data
      ③text/plain

      其中①application/x-www-form-urlencoded是默认值,大家可能在AJAX里见过这 个:xmlHttp.setRequestHeader("Content-Type","application/x-www-form- urlencoded"); 这两个要做的是同一件事情,就是设置表单传输的编码。在AJAX里不写有可能会报错,但是在HTML的form表单里是可以不写 enctype="application/x-www-form-urlencoded"的,因为默认HTML表单就是这种传输编码类型。而 ②multipart-form-data是用来指定传输数据的特殊类型的,主要就是我们上传的非文本的内容,比如图片或者mp3等等。 ③text/plain是纯文本传输的意思,在发送邮件时要设置这种编码类型,否则会出现接收时编码混乱的问题,网络上经常拿text/plain和 text/html做比较,其实这两个很好区分,前者用来传输纯文本文件,后者则是传递html代码的编码类型,在发送头文件时才用得上。①和③都不能用 于上传文件,只有multipart/form-data才能完整的传递文件数据。

      上面提到的MIME,它的英文全称是"Multipurpose Internet Mail Extensions" 多功能Internet 邮件扩充服务,它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。服务器会将它们发送的多媒体数据的类型告诉 浏览器,而通知手段就是说明该多媒体数据的MIME类型,从而让浏览器知道接收到的信息哪些是MP3文件,哪些是Shockwave文件等等。服务器将 MIME标志符放入传送的数据中来告诉浏览器使用哪种插件读取相关文件。

      简单说,MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

      浏览器接收到文件后,会进入插件系统进行查找,查找出哪种插件可以识别读取接收到的文件。如果浏览器不清楚调用哪种插件系统,它可能会告诉用户缺少某 插件,或者直接选择某现有插件来试图读取接收到的文件,后者可能会导致系统的崩溃。传输的信息中缺少MIME标识可能导致的情况很难估计,因为某些计算机 系统可能不会出现什么故障,但某些计算机可能就会因此而崩溃。


    检查一个服务器是否正确设置了MIME类型的步骤是:

      1. 在Netscape浏览器中打开服务器网页
      2. 进入"View"菜单,选择"Page Info"
      3. 在弹出的窗口中点击上层框架中的"EMBED"
      4. 在下层框架中查看MIME的类型是否为"application/x-director"或"application/x-shockwave- flash",如果是上述信息的话表明服务器已经正确设置了MIME类型;
              而如果MIME类型列出的是文本内容、八位一组的数据或是其它形式均表明服务器 的MIME类型没有设置正确。

      如果服务器没有正确标明其发送的数据的类型,服务器管理员应该正确添加相关信息,具体操作方法非常简单快捷。

      每个MIME类型由两部分组成,前面是数据的大类别,例如声音audio、图象image等,后面定义具体的种类

      常见的MIME类型

      
      超文本标记语言文本 .html,.html text/html

        普通文本 .txt text/plain

        RTF文本 .rtf application/rtf

        GIF图形 .gif image/gif

        JPEG图形 .jpeg,.jpg image/jpeg

        au声音文件 .au audio/basic

        MIDI音乐文件 mid,.midi audio/midi,audio/x-midi

        RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio

        MPEG文件 .mpg,.mpeg video/mpeg

        AVI文件 .avi video/x-msvideo

        GZIP文件 .gz application/x-gzip

        TAR文件 .tar application/x-tar

    Internet中有一个专门组织IANA来确认标准的MIME类型,但Internet发展的太快,很多应用程序等不及IANA来确认他们使用 的MIME类型为标准类型。因此他们使用在类别中以x-开头的方法标识这个类别还没有成为标准,例如:x-gzip,x-tar等。事实上这些类型运用的 很广泛,已经成为了事实标准。只要客户机和服务器共同承认这个MIME类型,即使它是不标准的类型也没有关系,客户程序就能根据MIME类型,采用具体的 处理手段来处理数据。而Web服务器和浏览器(包括操作系统)中,缺省都设置了标准的和常见的MIME类型,只有对于不常见的 MIME类型,才需要同时设置服务器和客户浏览器,以进行识别。
    ----------------------------------------------------------------
    表单中enctype="multipart/form-data"的意思,是设置表单的MIME编码。默认情况,
    这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;
    只有使用了multipart/form-data,才能完整的传递文件数据,进行下面的操作.
    enctype="multipart/form-data"是上传二进制数据; form里面的input的值以2进制的方式传过去。
    form里面的input的值以2进制的方式传过去,
    所以request就得不到值了。也就是说加了这段代码,用request就会传递不成功,取表单值加入数据库时,用到下面的:

    SmartUpload su = new SmartUpload();//新建一个SmartUpload对象
    su.getRequest().getParameterValues();取数组值
    su.getRequest().getParameter( );取单个参数单个值

    ajax中的application/x-www-form-urlencoded中的使用

    一,HTTP上传的基本知识

    在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型。下边是说明: application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。 multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。 text/plain:窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
    补充
    form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application /x-www-form-urlencoded。

    当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1& amp; amp;name2=value2...),然后把这个字串append到url后面,用?分割,加载这个新的url。

    当action为post时候,浏览器把form数据封装到http body中,然后发送到server。

    如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。但是如果有 type=file的话,就要用到multipart/form-data了。
    浏览器会把整个表单以控件为单位分割,并为每个部分加上 Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件 name)等信息,并加上分割符(boundary)。

    二,使用中需要注意的地方

    在AJAX往服务器上传数据是,设置了content-type为application/x-www-form-urlencoded,此时是对整个发 送内容作了编码,并不是对名字对应的值做了编码。因此,在服务器端,通过request.getParameter("name")的方式取值,是有问题 的。

    有两种解法办法:

    1)改服务器端: 采用流的方式硬编码

    复制代码
    InputStream stream=request.getInputStream();
    InputStreamReader isr=new InputStreamReader(stream);
    BufferedReader br=new BufferedReader(isr);
    String str=br.readLine(); 
    System.out.println(str);
    
    str=URLDecoder.decode(str,"gb2312");
    System.out.println(str);
    br.close();
    复制代码

    2)改客户端:更改数据发送结构

    在往服务器上发数据的时候,使用name=escape(value)的方式组对

    此时在服务器代码中,通过request.getParameter("name")获得的数值,就不用编码了

    application/x-www-form-urlencoded、multipart/form-data、text/plain

    http://www.cnblogs.com/mumue/archive/2012/05/24/2515984.html


    org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundaryRAYPKeHKTYSNdzc1;charset=UTF-8' not supported

    最近同事在做一个图片上传功能、在入参 body 中同时传入文件和其它基本信息结果出现如题异常、在此记录下解决办法、以做记录。

    controller 代码如下:

    复制代码
    @RequestMapping(value = "/upload", method =RequestMethod.POST)
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file, @RequestBody User user) {
    // 业务处理
    ......
    ......
    
    }
    复制代码

    在使用工具测试(Postman、 swagger )时报如下异常

    复制代码
      "timestamp": 1473349676109,
      "status": 415,
      "error": "Unsupported Media Type",
      "exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
      "message": "Content type 'multipart/form-data;boundary=----WebKitFormBoundaryTVc9eDC2a2elulOx;charset=UTF-8' not supported",
      "path": "/upload"
    复制代码

    解决方案:

    去掉 @RequestBody 注解就行了
    原因: 使用在进行图片或者文件上传时 multipart/form-data 类型时、 数据会自动进行映射不要添加任何注解。
    加了@RequestBody后,所以参数都会转换成JSON,会影响 POST中上报数据流的格式
    https://www.cnblogs.com/yueli/p/7552888.html

    关键词:理解 http 消息头
    使用 multipart form-data 上传 文件
    以前的章节已经介绍过了form传输表单的形式,但是在使用过程中仍然有很多问题,这里再向大家详细介绍一下。

    multipart/form-data是上传文件的一种方式。multipart/form-data其实就是浏览器用表单上传文件的方式。
    最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添加,也就是用multipart/form-data格式上传到服务器。

    具体的步骤如下:

    1、客户端和服务器建立链接(tcp协议)
    2、客户端可以向服务器发送数据
    3、客户端按照符合multipart/form-data的格式发送数据

    post /top/router/rest ?timestamp=2013-05-24%2010%3a14%3a48&method=taobao.item.update&title=title%20998&session=610231517b65e4e4e82575817e2d9169eeaac271cb91c55378591009&app_key=10011050&v=2.0&num_iid=13068812771&format=js on&sign=6570c00315a94edac47414b6e9b681e0 http/1.0
    content-type: multipart/form-data; boundary=------webkitformboundaryx3mhup4uhvo8zy3o
    accept-charset: utf-8
    host: gw.api.taobao.com
    connection: close
    content-length: 58294

    --------webkitformboundaryx3mhup4uhvo8zy3o
    content-disposition: form-data; name="image"; filename="pathddd.jpg"
    content-type: image/gif

    ......jfif.............c..................................省略的图片文件信息
    --------webkitformboundaryx3mhup4uhvo8zy3o--
    解释说明

    content-type: multipart/form-data; boundary=------webkitformboundaryx3mhup4uhvo8zy3o
    说明的是multipart/form-data格式的请求,boundary是一个字符串,用来切分数据。
    仔细查看,会发现body里面的bounday比header里面的前面都多了“--”。这是一个坑,我被搬到过。

    需要注意的是,在html协议中换行使用的是:" ",这我也被绊倒过。

    下面是lua拼写的上传服务器的代码:

    body = "--------webkitformboundaryx3mhup4uhvo8zy3o content-disposition: form-data; name="image"; filename="path\ddd.jpg" content-type: image/gif " .. body;
    body = body .. " --------webkitformboundaryx3mhup4uhvo8zy3o-- ";


    搜索此文相关文章:理解HTTP消息头 五——使用multipart/form-data上传文件
    此文链接:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%90%9C/30170.shtml

    postman进行访问服务器时,使用浏览器的url可以正常返回结果,但是postman却显示Could not get any response

    复制代码
    Could not get any response  
    This seems to be like an error connecting to http://pc.oma.com:9090/oma/venue/updateVenue.  
    Why this might have happened:  
    The server couldn't send a response:  
    Ensure that the backend is working properly  
    SSL connections are being blocked:  
    Fix this by importing SSL certificates in Chrome  
    Cookies not being sent:  
    Use the Postman Interceptor extension  
    Request timeout:  
    Change request timeout in Settings > General  
    复制代码

    解决办法:

    关闭防火墙。
    https://blog.csdn.net/sunny_12138/article/details/79196107

    原文地址:https://www.cnblogs.com/softidea/p/5745369.html

  • 相关阅读:
    SqlServer数据库同步方案详解(包括跨网段)
    makefile 和shell文件相互调用
    处理百万级以上的数据处理
    makefile Template(添加多个lib)
    Linux下如何删除非空目录
    makefile Template
    g++ 编译和链接
    gcc include路径
    C++ XML解析之TinyXML篇
    利用Lucene.net搭建站内搜索(2)分词技术
  • 原文地址:https://www.cnblogs.com/mmzuo-798/p/11634055.html
Copyright © 2020-2023  润新知