1. 程式人生 > >Http POST 提交資料的四種方式解析

Http POST 提交資料的四種方式解析

我們知道,HTTP 協議是以 ASCII 碼傳輸,建立在 TCP/IP 協議之上的應用層規範。HTTP 協議規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 這幾種。其中 POST 一般用來向服務端提交資料,本文主要討論 POST 提交資料的幾種方式。

協議規定 POST 提交的資料必須放在訊息主體(entity-body)中,但協議並沒有規定資料必須使用什麼編碼方式。但是,資料傳送出去,還要服務端解析成功才有意義。

服務端通常是根據請求頭(headers)中的 Content-Type 欄位來獲知請求中的訊息主體是用何種方式編碼,再對主體進行解析。

POST 提交資料方案,包含了 Content-Type 和訊息主體編碼方式兩部分。下面就正式開始介紹它們。

在伺服器端判斷request來自Ajax請求(非同步)還是傳統請求(同步):


xmlHttpRequest.png

application/x-www-form-urlencoded (預設常用的)

這應該是最常見的 POST 提交資料的方式了。瀏覽器的原生 <form> 表單,如果不設定 enctype
屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交資料。

Content-Type 被指定為 application/x-www-form-urlencoded;其次,提交的資料按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉碼。大部分服務端語言都對這種方式有很好的支援。例如 PHP 中,$_POST['title'] 可以獲取到 title 的值,$_POST['sub'] 可以得到 sub 陣列。


x-www-form-urlencoded.png

multipart/form-data

這又是一個常見的 POST 資料提交的方式。我們使用表單上傳檔案時,必須讓 <form> 表單的 enctyped
等於 multipart/form-data。直接來看一個請求示例:

提示 input type=file 瀏覽器處於安全考慮 , 必須操作賦值,不能直接改value,
比如canvas 直接生成圖片之後上傳 就不能使用 input type=file。可以直接把得到的圖片轉換成 base64 上傳


multipart/form-data.png

boundary 檔案分割線

application/json

application/json 這種方案,可以方便的提交複雜的結構化資料, 這個 Content-Type 作為響應頭大家肯定不陌生。現在越來越多的人把它作為請求頭,用來告訴服務端訊息主體是序列化後的 JSON 字串。

由於 JSON 規範的流行,除了低版本 IE 之外的各大瀏覽器都原生支援 JSON.stringify,服務端語言也都有處理 JSON 的函式,使用 JSON 不會遇上什麼麻煩。

JSON 格式支援比鍵值對複雜得多的結構化資料,這一點也很有用 AngularJS 中的 Ajax 功能,預設就是提交 JSON 字串。例如下面這段程式碼:

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

最終傳送的請求是:

Content-Type: application/json;charset=utf-8
 {"title":"test","sub":[1,2,3]}

application/json.png

JSON.parse()和JSON.stringify()


JSON.png

text/xml

現在幾乎不用

預設情況下,標準的跨域請求是不會發送cookie等使用者認證憑據的,XMLHttpRequest 2的一個重要改進就是提供了對授信請求訪問的支援。
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.xxx.com/api');
xhr.withCredentials = true;
xhr.onload = onLoadHandler;
xhr.send();

Access-Control-Allow-Credentials: true


Access-Control-Allow-Credentials.png