常见的四种POST 提交数据方式(小总结)


Posted in PHP onOctober 08, 2015

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

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

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

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

但是,数据发送出去,还要服务端成功解析才有意义。一般服务端语言如 php、python、Java、.NET 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。也就是说, Content-Type 指定了消息主体中的编码方式 。因此,POST 提交数据方案,直接跟 Content-Type 和消息主体两部分有关。

application/x-www-form-urlencoded

这是最常见的 POST 提交数据的方式。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据( enctype 的 POST 默认方式)。请求类似于下面(无关的请求头在本文中都省略掉了):

POST 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 的 enctyped 等于这个值。下面是示例:

POST 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 里指明了数据是以 mutipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 mutipart/form-data 的详细定义,请前往 rfc1867 查看。

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

上面两种 POST 数据方式,都是浏览器原生支持的,而且现阶段原生 form 表单也只支持这两种方式。但随着越来越多的 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 字符串。例如下面代码:

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

最终发送的请求是:

POST 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 请求是这样的:

POST 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 会更灵活方便。

以上内容是小编跟大家分享的常见的四种POST 提交数据方式,希望大家喜欢。

PHP 相关文章推荐
简体中文转换为繁体中文的PHP函数
Oct 09 PHP
简单示例AJAX结合PHP代码实现登录效果代码
Jul 25 PHP
快速开发一个PHP扩展图文教程
Dec 12 PHP
基于php中使用excel的简单介绍
Aug 02 PHP
PHP5各个版本的新功能和新特性总结
Mar 16 PHP
PHP实现把MySQL数据库导出为.sql文件实例(仿PHPMyadmin导出功能)
May 10 PHP
php防止用户重复提交表单
Nov 02 PHP
php通过会话控制实现身份验证实例
Oct 18 PHP
PHP与jquery实时显示网站在线人数实例详解
Dec 02 PHP
PDO::rollBack讲解
Jan 29 PHP
php和js实现根据子网掩码和ip计算子网功能示例
Nov 09 PHP
Thinkphp框架使用list_to_tree 实现无限级分类列出所有节点示例
Apr 04 PHP
PHP抽奖算法程序代码分享
Oct 08 #PHP
php视频拍照上传头像功能实现代码分享
Oct 08 #PHP
php+ajax 实现输入读取数据库显示匹配信息
Oct 08 #PHP
解决php的“It is not safe to rely on the system’s timezone settings”问题
Oct 08 #PHP
php 问卷调查结果统计
Oct 08 #PHP
JSON用法之将PHP数组转JS数组,JS如何接收PHP数组
Oct 08 #PHP
php开发微信支付获取用户地址
Oct 04 #PHP
You might like
社区(php&amp;&amp;mysql)六
2006/10/09 PHP
Zend Framework框架路由机制代码分析
2016/03/22 PHP
对laravel的session获取与存取方法详解
2019/10/08 PHP
Code: write(s,d) 输出连续字符串
2007/08/19 Javascript
高性能web开发 如何加载JS,JS应该放在什么位置?
2010/05/14 Javascript
jQuery代码优化 选择符篇
2011/11/01 Javascript
iframe调用父页面函数示例详解
2014/07/17 Javascript
用JavaScript实现对话框的教程
2015/06/04 Javascript
在JavaScript中处理时间之getHours()方法的使用
2015/06/10 Javascript
jQuery实现自定义右键菜单的树状菜单效果
2015/09/02 Javascript
javascript类型系统 Array对象学习笔记
2016/01/09 Javascript
使用Web Uploader实现多文件上传
2016/06/08 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
原生JS实现九宫格抽奖效果
2017/04/01 Javascript
详解Vue微信公众号开发踩坑全记录
2017/08/21 Javascript
vue中post请求以a=a&amp;b=b 的格式写遇到的问题
2018/04/27 Javascript
Vue-CLI3.x 设置反向代理的方法
2018/12/06 Javascript
wxPython窗口中文乱码解决方法
2014/10/11 Python
分享Python字符串关键点
2015/12/13 Python
Python脚本实现12306火车票查询系统
2016/09/30 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
2019/04/29 Python
Python实现不规则图形填充的思路
2020/02/02 Python
如何使用PyCharm将代码上传到GitHub上(图文详解)
2020/04/27 Python
Python判断远程服务器上Excel文件是否被人打开的方法
2020/07/13 Python
新奇的小玩意:IWOOT
2016/07/21 全球购物
Ellos丹麦:时尚和服装在线
2016/09/19 全球购物
美国时尚大码女装购物网站:Avenue
2019/05/24 全球购物
.NET程序员的几道面试题
2012/06/01 面试题
学院领导推荐信
2013/10/30 职场文书
大学生在校学习的自我评价
2014/02/18 职场文书
餐厅筹备计划书
2014/04/25 职场文书
2014大学生中国梦主题教育学习思想汇报
2014/09/10 职场文书
2014年庆祝国庆65周年演讲稿
2014/09/21 职场文书
师范生见习报告
2014/10/31 职场文书
2015年安康杯竞赛活动总结
2015/03/26 职场文书
mysql的MVCC多版本并发控制的实现
2021/04/14 MySQL