Ajax 請求頭中常見content-type


四種常見的 POST 提交數據方式

HTTP 協議是以 ASCII 碼傳輸,建立在 TCP/IP 協議之上的應用層規范。規范把 HTTP 請求分為三個部分:狀態行、請求頭、消息主體。協議規定 POST 提交的數據必須放在消息主體(entity-body)中,但協議並沒有規定數據必須使用什么編碼方式。實際上,開發者完全可以自己決定消息主體的格式,只要最后發送的 HTTP 請求滿足上面的格式就可以。

但是,數據發送出去,還要服務端解析成功才有意義。一般服務端語言如 php、python 等,以及它們的 framework,都內置了自動解析常見數據格式的功能。服務端通常是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體是用何種方式編碼,再對主體進行解析。所以說到 POST 提交數據方案,包含了 Content-Type 和消息主體編碼方式兩部分。下面我們一起來看看ajax中POST請求中的Content-Type。

(1)application/x-www-form-urlencoded

這應該是最常見的 POST 提交數據的方式了。瀏覽器的原生 form 表單,如果不設置 enctype 屬性,那么最終就會以 application/x-www-form-urlencoded 方式提交數據。請求類似於下面這樣:

 
application/x-www-form-urlencoded.png

首先,Content-Type 被指定為 application/x-www-form-urlencoded;其次,提交的數據按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 會進行了 URL 轉碼。大部分服務端語言都對這種方式有很好的支持。例如 PHP 中,$_POST['XXX'] 可以獲取到相應的值。

很多時候,我們用 Ajax 提交數據時,也是使用這種方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默認值都是「application/x-www-form-urlencoded;charset=utf-8」。如果你用js寫ajax要用這種方式,一定要注意加上setRequestHeader("Content-type","application/x-www-form-urlencoded");否則無法正常解析。

由於form表單會有默認事件,需要阻止默認事件(js用e.preventDefault()或return false;(ie) / jq用return false;),我們就直接在form表單上加onsubmit="return false;"。或者也可以直接不用form標簽。
html:

    <form id="myform" onsubmit="return false;"> 用戶名:<input type="text" id="username" name="username"/> 密碼:<input type="password" id="psw" name="psw"/><br/> <!-- 頭像:<input type="file" name="head"></form> --> <div class="button"> <button class="btn btn-primary" id="register">注冊</button> </div> </form> 

js:


 
js.png

jq:


 
jq.png
(2)multipart/form-data

這也是一個常見的 POST 數據提交的方式。我們使用表單上傳文件時,就要讓 form 的 enctype 等於這個值。直接來看一個請求示例:


 
multipart/form-data.png

這個例子稍微復雜點。首先生成了一個 boundary 用於分割不同的字段,為了避免與正文內容重復,boundary 很長很復雜。然后 Content-Type 里指明了數據是以 mutipart/form-data 來編碼,本次請求的 boundary 是什么內容。消息主體里按照字段個數又分為多個結構類似的部分,每部分都是以 --boundary 開始,緊接着內容描述信息,然后是回車,最后是字段具體內容(文本或二進制)。如果傳輸的是文件,還要包含文件名和文件類型信息。消息主體最后以 --boundary-- 標示結束。FormData 對象的更多內容點擊FormData 對象的使用

我們來看看具體實現:

js:

document.getElementById("register").addEventListener("click", function () { let form=document.getElementById("myform"); let formData = new FormData(form); var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) { console.log(xhr.responseText); } else { alert("Response was unsuccessful:" + xhr.status); } } }; xhr.open("post", "test.php", true); xhr.setRequestHeader("Content-Type","multipart/form-data"); xhr.send(formData); }) 

或jq:

$(document).ready(function(){ $("#register").click(function(){ var data = new FormData($('#myform')[0]); $.ajax({ url: 'test.php', type: 'POST', data: data, dataType: 'JSON', cache: false, processData: false, contentType: false }); return false; }); }); 

這種方式一般用來上傳文件,各大服務端語言對它也有着良好的支持。

上面提到的這兩種 POST 數據的方式,都是瀏覽器原生支持的,而且現階段原生 form 表單也只支持這兩種方式。但是隨着越來越多的 Web 站點,尤其是 WebApp,全部使用 Ajax 進行數據交互之后,我們完全可以定義新的數據提交方式,給開發帶來更多便利。

(3)application/json

application/json 這個 Content-Type 作為響應頭大家肯定不陌生。實際上,現在越來越多的人把它作為請求頭,用來告訴服務端消息主體是序列化后的 JSON 字符串。由於 JSON 規范的流行,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會遇上什么麻煩。

JSON 格式支持比鍵值對復雜得多的結構化數據,這一點也很有用。

在angular中,$http的contentType默認值是application/json;charset=UTF-8。例如下面這段代碼:

var data = {'title':'test', 'sub' : [1,2,3]}; $http.post(url, data).success(function(result) { ... }); 

我們在來看看js和jq中怎樣實現:

document.getElementById("register").onclick = function() { var request = new XMLHttpRequest(); request.open("POST", "test.php"); var data = {"username" :document.getElementById("username").value , "pwd" : document.getElementById("psw").value, } data=JSON.stringify(data); request.setRequestHeader("Content-type","application/json"); request.send(data); request.onreadystatechange = function() { if (request.readyState===4) { if (request.status===200) { var data = JSON.parse(request.responseText); if (data.id) { console.log(data.msg); } else { console.log("出現錯誤:" + data.msg); } } else { alert("發生錯誤:" + request.status); } } } } 
$("#register").click(function(){ var data={ "username": $("#username").val(), "pwd": $("#psw").val() }; data=JSON.stringify(data); $.ajax({ type: "POST", url: "test.php", data:data, dataType: "json", contentType:"application/json;charset=utf-8", success: function(data){ if (data.id) { console.log(data.msg); } else { console.log("出現錯誤:" + data.msg); } }, error: function(jqXHR){ alert("發生錯誤:" + jqXHR.status); }, }); }); 
 
application/json.png

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

(4)text/xml

相比於JSON,XML不能更好的適用於數據交換,它包含了太多的包裝, 而且它跟大多數編程語言的數據模型不匹配,讓大多數程序員感到詫異,XML是面向數據的,JSON是面向對象和結構的,后者會給程序員一種更加親切的感覺。

我們現在一般這樣來使用:
1、XML 存儲數據,存儲配置文件等需要結構化存儲的地方使用;
2、數據傳輸、數據交互使用JSON;
下面就是ajax Content-Type為text/xml的請求:


 
text/xml.png

js:

 document.getElementById("register").addEventListener("click",function (e){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){//返回 if(xhr.status==200){//響應代碼正常 var xmlObj=xhr.responseXML; //后台返回<res><mes>success</mes><user>patty</user></res> var res=xmlObj.getElementsByTagName("res")[0]; var mes=res.childNodes[0].childNodes[0].nodeValue; var user=res.childNodes[1].childNodes[0].nodeValue; console.log(mes+" 用戶:"+user); } } }; xhr.open("post", "test.php", true); var name=document.getElementsByName("username")[0].value; var pwd=document.getElementsByName("psw")[0].value; var xml="<user><name>"+name+"</name><pwd>"+pwd+"</pwd></user>"; xhr.setRequestHeader("Content-Type", "text/xml"); xhr.send(xml); }); 

jq:

$(document).ready(function(){ $("#register").click(function(){ var user=$("#username").val(); var pwd=$("#psw").val(); var data="<user><name>"+user+"</name><pwd>"+pwd+"</pwd></user>"; $.ajax({ type: "POST", url: "test.php", data:data, contentType:"text/xml", dataType: "XML", success: function(data){ var mes=$(data).find("res").children("mes").text(); var user=$(data).find("res").children("user").text() console.log(mes+" 用戶:"+user); }, error: function(jqXHR){ alert("發生錯誤:" + jqXHR.status); }, }); }); }); 

 


免責聲明!

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



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