本文所講的 POST 請求是 HTTP/1.1 協議中規定的眾多 HTTP 請求方法的其中最常用的一個。一般使用 POST 請求方法向伺服器傳送資料(主要是一些建立更新操作),本文討論的是 POST 請求方法常用的四種資料提交格式。
由於 HTTP/1.1 協議中並沒有對請求使用什麼編碼方式進行規定,所以理論上開發者完全可以自己決定請求的 Body 體使用什麼格式,當然實際上大家都還是用通用的那麼幾種編碼方式來提交資料(生態很關鍵)。
注:以下排名不分先後。。。
application/x-www-form-urlencoded
對於瀏覽器原生的 form 表單,enctype 的值不指定的話,預設就是這個傢伙。實際上大部分情況都使用它即可,編碼方式足夠簡單高效,各方面支援也都很完備,如各大瀏覽器除錯工具、各大抓包軟體等。
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
key1=val1&key2=val2
基本的請求類似上面這樣,資料的編碼方式採用 key1=val1&key2=val2 的形式,對其中的鍵值對都需要使用 URL Encode 編碼一下。其實就是和 GET 請求的資料提交格式是一樣的,只不過位置從 Request URL 上換到了 Request Body 裡。
這種格式結構簡單,但對於資料層級較深的情況,比如一些有複雜層級關係的介面資料,這種方式就顯得有點力不從心了。另一方面,對於需要上傳二進位制資料(比如影象、音訊等檔案),這種方式就不那麼高效了,而且對於非 ASCII 碼的資料就丟失了,所以傳檔案的情況就不能使用這種方式。
適用場景:資料量不大、資料層級不深的情況下強烈建議這種資料提交格式。
multipart/form-data
當你需要提交檔案、非 ASCII 碼的資料或者是二進位制流資料,則使用這種提交方式。類似下面這個請求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryPAlLG7hJKNYc4ft3
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
demo
------WebKitFormBoundaryPAlLG7hJKNYc4ft3
Content-Disposition: form-data; name="file"; filename="demo.png"
Content-Type: image/png
------WebKitFormBoundaryPAlLG7hJKNYc4ft3--
第二行指定編碼方式 Content-Type 為 multipart/form-data,緊接著生成一個分界線 boundary 即 ----WebKitFormBoundaryPAlLG7hJKNYc4ft3
,又臭又長的目的是為了避免和 Body 正文內容有衝突,它的作用是用來分隔不同的欄位。
Body 體分為多個結構類似的部分,每一部分以 --boundary
開頭,因為本次請求生成的 boundary 為 ----WebKitFormBoundaryPAlLG7hJKNYc4ft3
,所以最終是 ------WebKitFormBoundaryPAlLG7hJKNYc4ft3
。接著是描述內容的元資訊,包括欄位名稱,如果是檔案則還有檔名稱和檔案型別。接著留一空行,然後才是欄位值。什麼時候結束呢,以 --boundary--
標誌結束。
這種方式本就是專為上傳檔案的場景設計的,雖然你也可以使用這種方式傳遞普通資料,但無疑會增加不少資料包的大小(這麼多 boundary 還是有不少空間佔用的)。
適用場景:檔案上傳。
application/json
很明顯在 JSON 格式火之前,肯定沒有它的,前面說到使用什麼提交資料方式是沒有硬性規定的,所以在 JSON 格式火了以後,尤其以其優秀的資料結構表達能力,逐漸流行開來,現在我們對它完全不會陌生。
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"name":"xfly","age": 24, "hobby":["x","xx","xxx"]}
適用場景:資料結構較複雜,層級較深的情況。