前言
做過前後端聯調的小夥伴,可能有時會遇到一些問題。例如,我明明傳遞數據給後端了,後端爲什麼說沒收到呢?這時候可能就會就會有小夥伴陷入迷茫,本文從chrome-dev-tools(F12調試器)中看到的FormData
與RequestBody
,給小夥伴們提供一種可能的思路。也給小夥伴們提供一些問題的探究方法。
簡介
什麼是FormData?什麼是RequestPayload?不解釋,直接上圖:
區別?
因爲這裏觸及了我的知識盲區,所以有了本文。這個答案是我在stackoverflow
上得到的。首先還是貼問題,貼答案。
What's the difference between “Request Payload” vs “Form Data” as seen in Chrome dev tools Network tab。
中文翻譯:chrome開發者工具中的Request Payload與Form Data有什麼區別?
高票回答:
The Request Payload - or to be more precise: payload body of a HTTP Request - is the data normally send by a POST or PUT Request. It's the part after the headers and the CRLF of a HTTP Request.
A request with
Content-Type: application/json
may look like this:POST /some-path HTTP/1.1 Content-Type: application/json { "foo" : "bar", "name" : "John" }
If you submit this per AJAX the browser simply shows you what it is submitting as payload body. That’s all it can do because it has no idea where the data is coming from.
If you submit a HTML-Form with method="POST" and Content-Type: application/x-www-form-urlencoded or Content-Type: multipart/form-data your request may look like this:
POST /some-path HTTP/1.1 Content-Type: application/x-www-form-urlencoded foo=bar&name=John
In this case the form-data is the request payload. Here the Browser knows more: it knows that bar is the value of the input-field foo of the submitted form. And that’s what it is showing to you.
So, they differ in the Content-Type but not in the way data is submitted. In both cases the data is in the message-body. And Chrome distinguishes how the data is presented to you in the Developer Tools.
翻譯過來是說:Request Payload
更準確的說是http request的payload body
。一般用在數據通過POST
請求或者PUT
請求。它是HTTP
請求中空行的後面那部分。(PS:這裏涉及一個http常被問到的問題,http請求由哪幾部分組成,一般是請求行,請求頭,空行,請求體。payload body應該是對應請求體。)
一個請求伴隨着header設置爲Content-Type: application/json
時候,看起來可能像這樣:
POST /some-path HTTP/1.1
Content-Type: application/json
{ "foo" : "bar", "name" : "John" }
如果你正常請求一個ajax。瀏覽器會簡單的將你提交的內容作爲payload
展示出來,這就是它所能做的,因爲它不知道數據來自哪裏。
如果你提交了一個html表單並且配置上了method="post"
,並且設置了Content-Type: application/x-www-form-urlencoded
或者Content-Type: multipart/form-data
。那麼你的請求可能長這個樣:
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反饋來看:
注意點
1.默認的Content-Type
爲text/plain
。
2.Request Payload會對非字符串做字符串轉換。
3.通過xhr.send(JSON.stringify(obj));
可修正要發的內容
axios方式提交
場景構造
由於axios已經是vue、react的準標配請求方式了,所以這裏探究一下它。
首先我門看axios的文檔,當post提交時候可以傳遞什麼類型參數:
注意這個類型,我們分別構造兩個場景。對應它。
function submit3() {
var sence1 = 'name=123&val=456';
var sence2 = {name: 123, val: 456};
axios.post('/', sence1)
}
分別傳遞字符串與對象,提交post請求,然後觀察結果:
場景1——傳遞字符串時候的結果:
場景2——傳遞對象的結果:
注意點
1.當我們傳遞字符串的時候,Content-Type
自動轉爲xxx-form-xxx
的形式。當爲對象的時候,自動轉化爲xxx/json
。
2.字符串的時候以key1=val1&key2=val2
的形式體現,對象以JSON字符串形式體現。
總結
探索了這麼多種情況之後,那麼我們回顧一下:
Content-Type的差異
1.傳統的ajax請求時候,Content-Type
默認爲"文本"類型。
2.傳統的form提交的時候,Content-Type
默認爲"Form"類型。
3.axios傳遞字符串的時候,Content-Type
默認爲"Form"類型。
4.axios傳遞對象的時候,Content-Type
默認爲"JSON"類型
Content-Type的值,Form與非Form時,payload的區別。
1.都只支持字符串類型(以上探究的幾種情況)
2.Form需要傳遞的格式爲key1=value1&key2=value2
,類似GET
請求的QueryString
格式
- 非Form一般爲
JSON.stringify(formDataObject)
形式
後端取不到值?
無論何種形式傳遞,後端解析表單信息的時候,會考慮Content-Type
。如果是JSON字符串的話,後端解析payload的內容時候,肯定要用JSON.parse(str)
去解析啦。如果是key1=value1&key2=value2
的形式,則需要去分割字符串。
當然這些事情一般後端使用的框架會去處理,但是框架給後端提供取值接口有可能是不同的,所以前端的小夥伴在處理請求問題時,一定要跟後端小夥伴商量好,是用JSON
還是FormData
哈。
後記
本來只是小小的一個問題,仔細研究起來發現挺多細節。今天就花時間整理了一下,希望能給大家一些幫助。碼字不容易,如果感到這篇文章對你有用。點個贊,收個藏唄。