深入理解POST的本質

來源:互聯網
上載者:User

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操作。 

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

 伺服器端寫(asp.net ashx檔案) 

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

得到結果如下:

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="FA99781338524B308436CA61EAD537E5" border="0" alt="FA99781338524B308436CA61EAD537E5" height="149" src="http://www.bkjia.com/uploads/allimg/131228/12130I514-0.jpg" />

通過chrome也可以看到:

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="C86%60PG3DZ2REGCTVNKX7U(Q" border="0" alt="C86%60PG3DZ2REGCTVNKX7U(Q" height="253" src="http://www.bkjia.com/uploads/allimg/131228/12130J1Y-1.jpg" />

和通過提交表單的方式是一樣的效果。

再看一下Jquery的ajax方法。

其中data可以直接被賦值為key1=value1&key2=value2,如果有人喜歡json格式的賦值方式,那麼ajax方法參數中有一個屬性processData,預設是true,它會把json格式的資料轉換成key1=value1&key2=value2的格式。真是省心省力。如下,兩種賦值方式都可以寫,個人偏愛json方式,簡單明了。

 
  1. var option = { 
  2.             url: 'Handler1.ashx', 
  3.            type: 'POST', 
  4.             dataType: 'html', 
  5.             success: function (result) { 
  6.                 alert(result); 
  7.             }, 
  8.             //data: { data1: "Hello", data2: "World" }兩種寫法皆可以 
  9.             data: "data1=Hello&data2=World" 
  10.         }; 
  11.         $.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全是亂碼。

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="SMGD}9M)B6{8V~3%MSE%9]7" border="0" alt="SMGD}9M)B6{8V~3%MSE%9]7" height="83" src="http://www.bkjia.com/uploads/allimg/131228/12130Hc8-2.jpg" />

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="`WAIZCJA5VEF}L{(7%M]4C1" border="0" alt="`WAIZCJA5VEF}L{(7%M]4C1" height="245" src="http://www.bkjia.com/uploads/allimg/131228/12130L330-3.jpg" />

因此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部分:    

 
  1. var data = { "data": "testdata" }; 
  2.      var option = { 
  3.          url: 'Handler1.ashx', 
  4.          type: 'POST', 
  5.          data: JSON.stringify(data),//取得json的string 
  6.          dataType: 'html', 
  7.          contentType: 'application/json', 
  8.          success: function (result) { alert(result); } 
  9.      }; 
  10.      $.ajax(option); 

傳送的是application/json類型。那麼後台就得如下寫法:      

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

這裡的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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.