zoukankan      html  css  js  c++  java
  • 四种常见的 POST 提交数据方式

    定义和用法
    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 会更灵活方便。
     
     
    postman中 form-data、x-www-form-urlencoded、raw、binary的区别
    1、form-data: 
    就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。当上传的字段是文件时,会有Content-Type来表名文件类型;content-disposition,用来说明字段的一些信息;
    由于有boundary隔离,所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
     
    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( );取单个参数单个值
     
     
     

  • 相关阅读:
    韩国新地图格式
    这次是真的准备出售用于传奇开发的HGE图形引擎了
    减小Delphi2010程序的尺寸(关闭RTTI反射机制)
    hook api 保护进程
    使用静态库
    iOS中的Block动画
    IOS中忽略字符串两边空格比较
    判断是否输入有汉字
    EasyDSS产生cache缓存如何设定定时清理缓存?
    EasyDSS定制项目中ETCD服务挂掉如何设定定时重启?
  • 原文地址:https://www.cnblogs.com/absoluteli/p/13958112.html
Copyright © 2011-2022 走看看