from屬性EncType提交數(shù)據(jù)的格式詳解—在angular中的應(yīng)用


from屬性EncType提交數(shù)據(jù)的格式詳解—在angular中的應(yīng)用

我們知道,HTTP 協(xié)議是以 ASCII 碼傳輸,建立在 TCP/IP 協(xié)議之上的應(yīng)用層規(guī)范。規(guī)范把 HTTP 請(qǐng)求分為三個(gè)部分:狀態(tài)行、請(qǐng)求頭、消息主體。類似于下面這樣:

轉(zhuǎn)載請(qǐng)注明出處:http://www.zhoulujun.cn/zhoulujun/html/webfront/SGML/web/2017_0719_8034.html

協(xié)議規(guī)定 POST 提交的數(shù)據(jù)必須放在消息主體(entity-body)中,但協(xié)議并沒(méi)有規(guī)定數(shù)據(jù)必須使用什么編碼方式。實(shí)際上,開(kāi)發(fā)者完全可以自己決定消息主體的格式,只要最后發(fā)送的 HTTP 請(qǐng)求滿足上面的格式就可以。

但是,數(shù)據(jù)發(fā)送出去,還要服務(wù)端解析成功才有意義。一般服務(wù)端語(yǔ)言如 php、python 等,以及它們的 framework,都內(nèi)置了自動(dòng)解析常見(jiàn)數(shù)據(jù)格式的功能。服務(wù)端通常是根據(jù)請(qǐng)求頭(headers)中的 Content-Type 字段來(lái)獲知請(qǐng)求中的消息主體是用何種方式編碼,再對(duì)主體進(jìn)行解析。所以說(shuō)到 POST 提交數(shù)據(jù)方案,包含了 Content-Type 和消息主體編碼方式兩部分。

我們悉知,form表單屬性EncType表明提交數(shù)據(jù)的格式

用 Enctype 屬性指定將數(shù)據(jù)回發(fā)到服務(wù)器時(shí)瀏覽器使用的編碼類型。

下邊是說(shuō)明:

application/x-www-form-urlencoded: 窗體數(shù)據(jù)被編碼為名稱/值對(duì)。這是標(biāo)準(zhǔn)的編碼格式。一般默認(rèn)為application/x-www-form-urlencoded。

multipart/form-data: 窗體數(shù)據(jù)被編碼為一條消息,頁(yè)上的每個(gè)控件對(duì)應(yīng)消息中的一個(gè)部分。

text/plain: 窗體數(shù)據(jù)以純文本形式進(jìn)行編碼,其中不含任何控件或格式字符。

當(dāng)action為get時(shí)候,瀏覽器用x-www-form-urlencoded的編碼方式把form數(shù)據(jù)轉(zhuǎn)換成一個(gè)字串(name1=value1&name2=value2...),然后把這個(gè)字串a(chǎn)ppend到url后面,用?分割,加載這個(gè)新的url。

當(dāng)action為post時(shí)候,瀏覽器把form數(shù)據(jù)封裝到http body中,然后發(fā)送到server。

如果沒(méi)有type=file的控件,用默認(rèn)的application/x-www-form-urlencoded就可以了。

但是如果有type=file的話,就要用到multipart/form-data了。瀏覽器會(huì)把整個(gè)表單以控件為單位分割,并為每個(gè)部分加上Content-Disposition(form-data或者file),Content-Type(默認(rèn)為text/plain),name(控件name)等信息,并加上分割符(boundary)

在Form元素的語(yǔ)法中,EncType表明提交數(shù)據(jù)的格式 用 Enctype 屬性指定將數(shù)據(jù)回發(fā)到服務(wù)器時(shí)瀏覽器使用的編碼類型。 下邊是說(shuō)明: application/x-www-form-urlencoded: 窗體數(shù)據(jù)被編碼為名稱/值對(duì)。這是標(biāo)準(zhǔn)的編碼格式。 multipart/form-data: 窗體數(shù)據(jù)被編碼為一條消息,頁(yè)上的每個(gè)控件對(duì)應(yīng)消息中的一個(gè)部分。 text/plain: 窗體數(shù)據(jù)以純文本形式進(jìn)行編碼,其中不含任何控件或格式字符。

application/x-www-form-urlencoded

這應(yīng)該是最常見(jiàn)的 POST 提交數(shù)據(jù)的方式了。瀏覽器的原生

首先,Content-Type 被指定為 application/x-www-form-urlencoded;其次,提交的數(shù)據(jù)按照 key1=val1&key2=val2 的方式進(jìn)行編碼,key 和 val 都進(jìn)行了 URL 轉(zhuǎn)碼。大部分服務(wù)端語(yǔ)言都對(duì)這種方式有很好的支持。例如 PHP 中,$_POST['title'] 可以獲取到 title 的值,$_POST['sub'] 可以得到 sub 數(shù)組。

很多時(shí)候,我們用 Ajax 提交數(shù)據(jù)時(shí),也是使用這種方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默認(rèn)值都是「application/x-www-form-urlencoded;charset=utf-8」。

multipart/form-data

這又是一個(gè)常見(jiàn)的 POST 數(shù)據(jù)提交的方式。我們使用表單上傳文件時(shí),必須讓

POST?http://www.example.com?HTTP/1.1

Content-Type:multipart/form-data;?boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition:?form-data;?name="text"title

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition:?form-data;?name="file";?filename="chrome.png"Content-Type:?image/png

PNG?...?content?of?chrome.png?...

------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

這個(gè)例子稍微復(fù)雜點(diǎn)。首先生成了一個(gè) boundary 用于分割不同的字段,為了避免與正文內(nèi)容重復(fù),boundary 很長(zhǎng)很復(fù)雜。然后 Content-Type 里指明了數(shù)據(jù)是以 multipart/form-data 來(lái)編碼,本次請(qǐng)求的 boundary 是什么內(nèi)容。消息主體里按照字段個(gè)數(shù)又分為多個(gè)結(jié)構(gòu)類似的部分,每部分都是以--boundary開(kāi)始,緊接著是內(nèi)容描述信息,然后是回車,最后是字段具體內(nèi)容(文本或二進(jìn)制)。如果傳輸?shù)氖俏募?,還要包含文件名和文件類型信息。消息主體最后以--boundary--標(biāo)示結(jié)束。關(guān)于 multipart/form-data 的詳細(xì)定義,請(qǐng)前往 rfc1867 查看。

這種方式一般用來(lái)上傳文件,各大服務(wù)端語(yǔ)言對(duì)它也有著良好的支持。

上面提到的這兩種 POST 數(shù)據(jù)的方式,都是瀏覽器原生支持的,而且現(xiàn)階段標(biāo)準(zhǔn)中原生

隨著越來(lái)越多的 Web 站點(diǎn),尤其是 WebApp,全部使用 Ajax 進(jìn)行數(shù)據(jù)交互之后,我們完全可以定義新的數(shù)據(jù)提交方式,給開(kāi)發(fā)帶來(lái)更多便利。

application/json

application/json 這個(gè) Content-Type 作為響應(yīng)頭大家肯定不陌生。實(shí)際上,現(xiàn)在越來(lái)越多的人把它作為請(qǐng)求頭,用來(lái)告訴服務(wù)端消息主體是序列化后的 JSON 字符串。由于 JSON 規(guī)范的流行,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務(wù)端語(yǔ)言也都有處理 JSON 的函數(shù),使用 JSON 不會(huì)遇上什么麻煩。

JSON 格式支持比鍵值對(duì)復(fù)雜得多的結(jié)構(gòu)化數(shù)據(jù),這一點(diǎn)也很有用。記得我?guī)啄昵白鲆粋€(gè)項(xiàng)目時(shí),需要提交的數(shù)據(jù)層次非常深,我就是把數(shù)據(jù) JSON 序列化之后來(lái)提交的。不過(guò)當(dāng)時(shí)我是把 JSON 字符串作為 val,仍然放在鍵值對(duì)里,以 x-www-form-urlencoded 方式提交。

Google 的 AngularJS 中的 Ajax 功能,默認(rèn)就是提交 JSON 字符串。例如下面這段代碼:

var?data?=?{'title':'test',?'sub'?:?[1,2,3]};

$http.post(url,?data).success(function(result)?{

...

});

最終發(fā)送的請(qǐng)求是:

BASHPOST?http://www.example.com?HTTP/1.1

Content-Type:?application/json;charset=utf-8

{"title":"test","sub":[1,2,3]}

這種方案,可以方便的提交復(fù)雜的結(jié)構(gòu)化數(shù)據(jù),特別適合 RESTful 的接口。各大抓包工具如 Chrome 自帶的開(kāi)發(fā)者工具、Firebug、Fiddler,都會(huì)以樹(shù)形結(jié)構(gòu)展示 JSON 數(shù)據(jù),非常友好。但也有些服務(wù)端語(yǔ)言還沒(méi)有支持這種方式,例如 php 就無(wú)法通過(guò) $_POST 對(duì)象從上面的請(qǐng)求中獲得內(nèi)容。這時(shí)候,需要自己動(dòng)手處理下:在請(qǐng)求頭中 Content-Type 為 application/json 時(shí),從php://input里獲得原始輸入流,再json_decode成對(duì)象。一些 php 框架已經(jīng)開(kāi)始這么做了。

angularjs默認(rèn)就是采用這種模式,如果需要,更改angular請(qǐng)求模式,一般請(qǐng)求:

$http({

method:?'POST',

cache:?false,

data:?data,

headers:?{?'Content-Type':?'application/x-www-form-urlencoded;?charset=UTF-8'},

transformRequest:?function(obj)?{

console.log('?$httpProvider.defaults.transformRequest?=?function(obj)?{');

console.log(obj);

var?str?=?[];

for?(var?p?in?obj)

str.push(encodeURIComponent(p)?+?"="?+?encodeURIComponent(obj[p]));

return?str.join("&");

},

url:?"syf-merchant/uploadMerchantRegPic"

}).success(function?(response)?{

}).error(function?()?{

CommonService.showMessage('上傳失敗,請(qǐng)稍后再試')

})

};

當(dāng)然,也可以,直接攔截所有請(qǐng)求,轉(zhuǎn)換:

/*?我的攔截器?*/

$httpProvider.defaults.headers.post['Content-Type']?=?'application/x-www-form-urlencoded;charset=UTF-8';

$httpProvider.defaults.transformRequest?=?function(obj)?{

console.log('?$httpProvider.defaults.transformRequest?=?function(obj)?{');

console.log(obj);

var?str?=?[];

for?(var?p?in?obj)

str.push(encodeURIComponent(p)?+?"="?+?encodeURIComponent(obj[p]));

return?str.join("&");

};

參考文章:

https://imququ.com/post/four-ways-to-post-data-in-http.html

http://www.cnblogs.com/sunxucool/archive/2012/12/11/2813113.html

轉(zhuǎn)載請(qǐng)注明出處:http://www.zhoulujun.cn/zhoulujun/html/webfront/SGML/web/2017_0719_8034.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容