form-data和x-www-form-urlencode的區別


使用post請求發送數據時候,數據會放在body部分而不是頭信息中,而數據放在body中傳輸時候,我們可以將這個body中的信息看作是一個長長的單個字符串,而我們使用不同的編碼就是將這個數據用不同的形式進行發送。

application/x-www-form-urlencoded

原理

它是post的默認格式,它默認使用了一些特殊的符號作為分割符,例如&(ascii碼為0x26)=(0x3D)(空格)等,我們input中的name、value信息會發送時使用=連接,不同的input之間使用&連接;在接收端使用相同方式進行解碼,一旦遇到&,=等字符將會按照規定將這個長字節斷開,還原為原來key:value 形式的數據,以供我們使用。所以使用這種格式解碼時,可以看作是一個個字節進行掃描的,並使用特殊的字節將其不同的部分區分。

問題

這種方式發送一個非特殊字符的單字節字符時沒有問題的,當我們需要發送一個多字節字符,例如中文的字,如果直接使用utf-8編碼發送,其編碼為0xE4B8AD,會使用三個字節傳輸,分別為0xE40xB80xAD,當某些中文或者多字節的字符發送時,恰好有一個字節解碼為0x26或者0x3D時,這個多字節字符中一個字節將會被接收段解碼為=&符號這中特殊字節,從而將數據從此處斷開,產生數據的錯誤。

為了解決這個問題,使用了JS中URLencode轉碼方法,也就是URL編碼,我們經常看到一個URL類似於https://cn.bing.com/search?q=ascii%E7%A0%81%E8%A1%A8, %E7%A0%81%E8%A1%A8就是經過這種編碼方式產生的。我們發送上面的,utf-8編碼為0xE4B8AD(這是3個字節的16進制表示法,它表示的字符是一個字符),不能直接進行發送。需要使用URLencode進行轉碼,使用這個編碼的16進制形式的字符串為基礎,每兩個字符前添加一個%,得到字符串%E4%B8%AD(這是一個字符串,每一個字符都是一個字節,這里總共9個字節),再將這個字節發送。這樣就解決了上面的問題。

使用這中方式發送的數據,一個中文將會被編碼為9個字節進行發送,在發送大量的中文及多字符數據時會嚴重的浪費網絡帶寬資源,一般在發送少量的數據使用。例如下面是在一個表單中發送{country: 中國, city:北京}信息時候,瀏覽器發送的部分信息

POST /users/ HTTP/1.1 Host: localhost:8000 Content-Type: application/x-www-form-urlencoded // 頭中指定格式 country=%E4%B8%AD%E5%9B%BD&city=%E5%8C%97%E4%BA%AC // 編碼后的數據 

form-data

application/x-www-form-urlencoded必須進行多字節字符的編碼,這是由於多字節字符的單個字節信息可能與特殊字節信息沖突。而form-data的解決方法就是, 不在使用這些單個字節的特殊字符作為特殊分割,而是告訴對方使用分割字符串。上面的{country: 中國, city:北京}表單信息使用這種格式發送時,瀏覽器發送的數據為。

POST /users/ HTTP/1.1 Host: localhost:8000 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW--, Content-Disposition: form-data; name="country" 中國 ------WebKitFormBoundary7MA4YWxkTrZu0gW-- Content-Disposition: form-data; name="city" 北京 ------WebKitFormBoundary7MA4YWxkTrZu0gW-- 
HASKELL 復制 全屏

在header頭信息中,Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW分別指定了格式和 boundary(分割字符串),在body中使用了這個boundary指定的字符串作為分割,從而可以輕易的還原為key:value的形式。這里的中國北京中,每一個字符l例如,都是直接使用utf-8編碼(大部分網絡傳輸都使用該編碼)后進行傳輸的,也就是說每個中文只需要3個字節。

總結

application/x-www-form-urlencoded 他能簡潔的將key:value的數據進行分割。這一點相比form-data使用長長的字符串作為分割符優勢巨大,雖然對於多字節的數據會因為編碼造成字節量劇增(可以看到一個中文字符增加了2倍字節量),但是在單字節或者是少量的數據時,這種方式是划算的。
form-data 是一種重視數據的方式,通常我們在value值中會發送大量的文本信息,或者直接的傳送一個文件,數據直接編碼為二進制發送,不會產生多余的字節,適合大文本的傳輸。


 

 

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

<form action="form_action.asp" enctype="text/plain">
  <p>First name: <input type="text" name="fname" /></p>
  <p>Last name: <input type="text" name="lname" /></p>
  <input type="submit" value="Submit" />
</form>

此時可以看到,

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 轉碼。大部分服務端語言都對這種方式很好的支持,常用的如jQuery中的ajax請求,Content-Type 默認值都是「application/x-www-form-urlencoded;charset=utf-8

(2)multipart/form-data
這也是常見的post請求方式,一般用來上傳文件,各大服務器的支持也比較好。所以我們使用表單 上傳文件 時,必須讓<form>表單的enctype屬性值為 multipart/form-data.

注意:以上兩種方式:application/x-www-form-urlencoded和multipart/form-data都是瀏覽器原生支持的。

(3)application/json
application/json作為響應頭並不陌生,實際上,現在很多時候也把它作為請求頭,用來告訴服務端消息主體是序列化的JSON字符串,除了低版本的IE,基本都支持。除了低版本的IE都支持JSON.stringify()的方法,服務端也有處理JSON的函數,使用json不會有任何麻煩。例如:

復制代碼
復制代碼
//請求數據
var data = {name:'jack',sex:'man'};
//請求數據序列化處理
JSON.stingify(data);

//結果:{'name':'jack','sex':'man'};
復制代碼
復制代碼

二、postman的幾種參數格式

form-data、x-www-form-urlencoded、raw、binary的區別

1.form-data對應的是頁以form表單提交傳值的情形

等價於http請求中的multipart/form-data,它會將表單的數據處理為一條消息,以標簽為單元,用分隔符分開。既可以上傳鍵值對,也可以上傳文件。當上傳的字段是文件時,會有Content-Type來表名文件類型;content-disposition,用來說明字段的一些信息;
由於有boundary隔離,所以multipart/form-data既可以上傳文件,也可以上傳鍵值對,它采用了鍵值對的方式,所以可以上傳多個文件

復制代碼
復制代碼
POST  HTTP/1.1
Host: test.app.com
Cache-Control: no-cache
Postman-Token: 59227787-c438-361d-fbe1-75feeb78047e
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="filekey"; filename=""
Content-Type: 


------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="textkey"

tttttt
------WebKitFormBoundary7MA4YWxkTrZu0gW--
復制代碼
復制代碼

請求體中的boundary參數指定的就是分隔體,可以看到請求內容被分為了兩段,第一段對應filekey,第二段對應textkey。

2. x-www-form-urlencoded
即application/x-www-from-urlencoded,將表單內的數據轉換為Key-Value。

復制代碼
復制代碼
POST  HTTP/1.1
Host: test.app.com
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: e00dbaf5-15e8-3667-6fc5-48ee3cc89758

key1=value1&key2=value2
復制代碼
復制代碼

form-data與x-www-form-urlencoded的區別

  • multipart/form-data:可以上傳文件或者鍵值對,最后都會轉化為一條消息
  • x-www-form-urlencoded:只能上傳鍵值對,而且鍵值對都是通過&間隔分開的

3.raw對應的是入參是任意格式的可以上傳任意格式的【文本】,可以上傳text、json、xml、html等

 

(4)binary

相當於Content-Type:application/octet-stream,只可以上傳二進制數據,通常用來上傳文件,但是一次只能上傳一個文件

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM