您的位置:首页 > 其它

深入理解POST的本质

2013-01-10 16:50 155 查看
HTTP中,提交数据的方式,最常用的就是GET和POST。

GET方式,搞WEB开发的都很熟悉,其实就是把参数编程键值对通过QueryString的方式放在URL尾部,比如:

http://xxxx.com/test.aspx?a=1&b=2

POST方法,通常就是把要提交的表单放在一个FORM中,指明action后就可以提交数据。没有发现有诸如?a=1&b=2这样的键值对出现。

其实大家都被屏蔽了。事实上,打开W3C官网,可以看到如下

When the user submits a form (e.g., by activating a submit button), the user agent processes it as follows.
Step one: Identify the successful controls
Step two: Build a form data set
A form data set is a sequence of control-name/current-value pairs constructed from successful controls
Step three: Encode the form data set
The form data set is then encoded according to the content type specified by the enctype attribute of the FORM element.
Step four: Submit the encoded form data set
清楚的写到,第三步,对数据编码。根据 content type的内容指定的进行编码。

If the method is "get" and the action is an HTTP URI, the user agent takes the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type. The user agent then traverses the link to this URI. In this scenario, form data are restricted to ASCII codes.
If the method is "post" and the action is an HTTP URI, the user agent conducts an HTTP "post" transaction using the value of the action attribute and a message created according to the content type specified by the enctype attribute.
如果方法是get的,就用问号,编码方式按照"application/x-www-form-urlencoded" 进行。user agent实际上指的就是浏览器,它会处理这一切,并指向一个编码后生成的Link。

如果是post方式,则会看使用哪种content type来编码。通过属性enctype指定编码content type的。

POST支持的content type方式有2种,默认的content type是application/x-www-form-urlencoded 。这种编码方式,其实也就是把表单名字和值组成键值对的形式,用‘&’符号连接该转码的转码拼接成个get方式差不多的那种格式。如原文写道:

application/x-www-form-urlencoded
This is the default content type. Forms submitted with this content type must be encoded as follows:
Control names and values are escaped. Space characters are replaced by `+', and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by `%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A').
The control names/values are listed in the order they appear in the document. The name is separated from the value by `=' and name/value pairs are separated from each other by `&'.
当然HTML4.0后还有multipart/form-data格式的,用来POST文件等二进制数据的。有兴趣的可以自己研究一下。

POST方式其实也是转成这种键值对的形式来post的,那么我们可以自己编写键值对,来post数据了吧?当然可以。其实Jquery中就是这么用的。先看个例子。直接使用原生的XMLHttpRequest来作POST操作。

<script type="text/javascript">
var objHTTP, strResult;
objHTTP = new XMLHttpRequest();
objHTTP.open('POST', "Handler1.ashx", false);
objHTTP.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
objHTTP.send("data1=Hello&data2=Wrold");
strResult = objHTTP.responseText;
alert(strResult);
</script>

服务器端写(asp.net ashx文件)

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string s = context.Request["data1"] +" "+ context.Request["data2"];
context.Response.Write(s);
}
</script>

得到结果如下:





通过chrome也可以看到:





和通过提交表单的方式是一样的效果。

再看一下Jquery的ajax方法。

其中data可以直接被赋值为key1=value1&key2=value2,如果有人喜欢json格式的赋值方式,那么ajax方法参数中有一个属性processData,默认是true,它会把json格式的数据转换成key1=value1&key2=value2的格式。真是省心省力。如下,两种赋值方式都可以写,个人偏爱json方式,简单明了。

var option = {
url: 'Handler1.ashx',
type: 'POST',
dataType: 'html',
success: function (result) {
alert(result);
},
//data: { data1: "Hello", data2: "World" }两种写法皆可以
data: "data1=Hello&data2=World"
};
$.ajax(option);

注意,这种方式,默认的'Content-Type'都是'application/x-www-form-urlencoded'。如果更换Content-Type,就需要把processData设成false,同时,data的内容要自己自己控制好。

要用ajax方式Post文件就比较困难,因为Content-Type为multipart/form-data,而data无法手动赋值,因此比较困难。用firebug,查看post的一个doc文件,发现post的data全是乱码。









因此ajax方式上传文件一般都是包含一个<frame>或者使用flash的方式上传文件。

如果指明Content-Type是'application/json',那么data需要的是JSON的string,使用方法JSON.stringify(jsondata)可以获得这种string。但是要注意一点,不使用默认的application/x-www-form-urlencoded,数据是不会在Form Data中的,也就是用传统Request["data"]方法是获得不到数据的。对于特殊格式的数据就要特殊办法处理。那处理的方式就是强行读取Request.InputStream。当然对于默认的application/x-www-form-urlencoded也是可以采用这种最原始但是最有效的。

比如下面的例子:js部分:

var data = { "data": "testdata" };
var option = {
url: 'Handler1.ashx',
type: 'POST',
data: JSON.stringify(data),//取得json的string
dataType: 'html',
contentType: 'application/json',
success: function (result) { alert(result); }
};
$.ajax(option);

传送的是application/json类型。那么后台就得如下写法:

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
StreamReader sr = new StreamReader(context.Request.InputStream, Encoding.UTF8);
string s=sr.ReadToEnd();
context.Response.Write(s);
}

这里的s就是纯的json字符串,要转变成json对象可以使用JSON.NET或者FastJson等第三方类库来实现。

================

参考资料
http://en.wikipedia.org/wiki/POST_(HTTP) http://www.w3.org/TR/html4/interact/forms.html http://en.wikipedia.org/wiki/XMLHttpRequest 本文出自 “一只博客” 博客,请务必保留此出处http://cnn237111.blog.51cto.com/2359144/1113546
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: