今天中午在領完盒飯,吃飯的時候,爲了趕進度,不得不一邊吃飯,一邊敲代碼,爲了給後端傳一張圖片,我用new FormData()
把圖片append
進去,模擬form
表單提交,慌慌張張,匆匆忙忙,覺得弄完就能夠開心的吃飯了,結果後端說沒有收到數據...我明明傳遞數據給後端了,後端爲何說沒收到呢?下面就進入咱們此次的主題html
什麼是Form Data
?什麼是RequestPayload
?FormData
和Payload
是瀏覽器傳輸給接口的兩種格式,這兩種方式瀏覽器是經過Content-Type
的值來進行區分的:前端
application/x-www-form-urlencoded
的話,則爲Form Data
方式application/json
或multipart/form-data
的話,則爲 RequestPayload
的方式。POST
提交中Content-Type |
請求格式 |
---|---|
application/x-www-form-urlencoded |
formdata |
application/json |
request payload |
multipart/form-data |
request payload |
從MDN的MIME類型這篇文章能夠看到:multipart/form-data
可用於HTML
表單從瀏覽器發送信息給服務器。做爲多部分文檔格式,它由邊界線(一個由'--'開始的字符串)劃分出的不一樣部分組成。每一部分有本身的實體,以及本身的 HTTP
請求頭,Content-Disposition
和 Content-Type
用於文件上傳領域,最經常使用的 (Content-Length
由於邊界線做爲分隔符而被忽略)。以下圖所示:jquery
Form Data
Content-Type: multipart/form-data; boundary=aBoundaryString
(other headers associated with the multipart document as a whole)
--aBoundaryString
Content-Disposition: form-data; name="myFile"; filename="img.jpg"
Content-Type: image/jpeg
(data)
--aBoundaryString
Content-Disposition: form-data; name="myField"
(data)
--aBoundaryString
(more subparts)
--aBoundaryString--
複製代碼
Request Paload
解釋以下: FormData
和Payload
是瀏覽器傳輸給接口的兩種格式,這兩種方式瀏覽器是經過Content-Type
的值來進行區分的,若是是 application/x-www-form-urlencoded
的話,則爲Form Data
方式,若是是application/json
或multipart/form-data
的話,則爲 RequestPayload
的方式。ios
參考連接: stackoverflow.com/questions/2… 其中的解釋以下:ajax
一個請求伴隨着時候,看起來可能像這樣:chrome
POST /some-path HTTP/1.1
Content-Type: application/json
{ "foo" : "bar", "name" : "John" }
複製代碼
若是你只是簡單的ajax
請求。請求的header
將設置爲Content-Type: application/json
。瀏覽器會簡單的將你提交的內容做爲payload
展現出來,這就是它所能作的,由於它不知道數據來自哪裏。json
若是你提交了一個html
表單而且配置上了method="post"
,而且設置了Content-Type: application/x-www-form-urlencoded
或者Content-Type: multipart/form-data
。那麼你的請求可能長這個樣:axios
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded
foo=bar&name=John
複製代碼
這裏的form-data
就是request payload
。在這裏,瀏覽器知道更多:它知道bar
是提交表單的輸入字段foo
的值。這就是它向你展現的。後端
因此區別就是,他們只是由於Content-Type
設置的不一樣,並非數據提交方式的不一樣,這兩種提交都會將數據放在message-body
中。可是chrome
瀏覽器的開發者工具會根據這個ContentType
區分顯示方式。瀏覽器
payload
中。
那麼具體有什麼區別呢?爲何有時候後端拿不到值呢?這就不得不說對
payload
的解析方式了。咱們以幾個
chrome
下的測試案例,來理一理這個邏輯。
傳統的Form表單
提交場景構造以下:
<form action="/" method="POST">
<input name="name" type="text">
<input name="password" type="text">
<button>提交</button>
</form>
複製代碼
若是我這裏點擊提交按鈕,就會觸發瀏覽器的提交功能,那結果是什麼樣呢?
能夠看到Content-Type
爲application/x-www-form-urlencoded
。 值的形式是以key1=value1&key2=value2
的形式提交的。
傳統的ajax
提交 場景構造
function submit2() {
var xhr = new XMLHttpRequest();
xhr.timeout = 3000;
var obj = {a: 1, b: 2};
xhr.open('POST', '/');
xhr.send(obj);
}
複製代碼
首先咱們構造一個簡單的函數,而後觸發它。經過chrome
反饋來看:
傳統ajax
提交須要注意如下幾點
的Content-Type
爲text/plain
。Request Payload
會對非字符串作字符串轉換。xhr.send(JSON.stringify(obj))
;可修正要發的內容注意點
Content-Type
自動轉爲xxx-form-xxx
的形式。當爲對象的時候,自動轉化爲xxx/json
。key1=val1&key2=val2
的形式體現,對象以JSON
字符串形式體現。Content-Type
的差別ajax
請求時候,Content-Typ
e默認爲文本
類型。form
提交的時候,Content-Type
默認爲Form
類型。axios
傳遞字符串的時候,Content-Type
默認爲Form
類型。axios
傳遞對象的時候,Content-Type
默認爲JSON
類型。Content-Type
的值,Form
與非Form
時,payload
的區別:Form
須要傳遞的格式爲key1=value1&key2=value2
,相似GET
請求的QueryString
格式Form
通常爲JSON.stringify(formDataObject)
形式所以後端若是取不到值,不管何種形式傳遞,後端解析表單信息的時候,會考慮Content-Type
。若是是JSON
字符串的話,後端解析payload
的內容時候,確定要去解析JSON
。若是是key1=value1&key2=value2
的形式,則須要去分割字符串。這些事情通常後端使用的框架會去處理,可是框架給後端提供取值接口有多是不一樣的,因此前端的小夥伴在處理請求問題時,必定要跟後端小夥伴商量好,是用JSON
仍是FormData
。
參考資料:
text/html
: HTML格式text/plain
:純文本格式text/xml
: XML格式image/gif
:gif圖片格式image/jpeg
:jpg圖片格式image/png
:png圖片格式application
開頭的媒體格式類型:application/xhtml+xml
:XHTML格式application/xml
: XML數據格式application/atom+xml
:Atom XML聚合格式application/json
: JSON數據格式application/pdf
:pdf格式application/msword
: Word文檔格式application/octet-stream
: 二進制流數據(如常見的文件下載)application/x-www-form-urlencoded
: <form encType=」」>
中默認的encType
,form
表單數據被編碼爲key/value
格式發送到服務器(表單默認的提交數據的格式)multipart/form-data
: 須要在表單中進行文件上傳時,就須要使用該格式