Ajax方式提交表單的常見編碼類型總結

以前一篇文章(表單提交時編碼類型enctype詳解)介紹了表單屬性enctype的編碼類型,今天來說一講Ajax方式提交表單時經常使用的編碼類型。前端

用Ajax方式提交表單,決定編碼類型的是請求頭中Content-Type,不一樣的值對應不一樣的提交和回調處理方式。並且,在項目中咱們會用到前端的庫或者框架,他們對於不一樣的Content-Type也有不一樣的參數寫法,本文將以jQueryAngularJS,加上XMLHttpRequest共三種方式爲例,詳細介紹不一樣Content-Type的發送請求的方式。
本文考慮的Content-Type類型,共有以下幾種:jquery

  • application/x-www-form-urlencodedajax

  • multipart/form-datajson

  • text/plainsegmentfault

  • application/json後端

  • text/xml瀏覽器

下面將介紹XMLHttpRequest、jQuery和AngularJS三種異步提交方式,及對應的每一種Conten-Type類型。app

XMLHttpRequest 方式

XMLHttpRequest對象用於向後端收發數據請求,現代瀏覽器都支持(IE要用ActiveXObject實現相同功能,本文就不討論了)。框架

後續代碼將假設已經得到了XMLHttpRequest對象,其名爲req。下面將介紹XMLHttpRequest對象用常見的五種Content-Type發送數據的方式。異步

application/x-www-form-urlencoded

這種Content-Type要求數據按照key1=value1&key2=value2的格式發送給後端,且其中的特殊字符須要轉義成%HH的形式。

首先,須要用encodeURIComponent()函數編碼表單數據,代碼以下。

/* data參數爲表單數據組成的對象,dataToSend爲待發送給後端的數據 */

var tempArr = [];
for (var key in data) {
    if (data.hasOwnProperty(key)) {
        tempArr.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
    }
}

var dataToSend = tempArr.join('&');

接着,設置請求頭部的Content-Type,發送數據,代碼以下。

req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(dataTosend);

multipart/form-data

這種Content-Type類型多用來提交文件,咱們採用HTML5的FormData對象來構建提交的數據。FormData對象的瀏覽器支持狀況見:FormData對象的瀏覽器支持狀況
基本上現代瀏覽器都支持,IE11如下不支持,不支持的建議用ajaxForm之類的jquery的文件提交插件吧。

首先,用FormData對象構建欲提交的數據,代碼以下。

/* data參數爲表單數據組成的對象,dataToSend爲待發送給後端的數據 */

var dataToSend = new FormData();      // HTML5對象, IE11如下不支持
for (var key in data) {
    if (data.hasOwnProperty(key)) {
        dataToSend.append(key, data[key]);
    }
}

// dataToSend就是FormData對象,可直接傳給後端
dataToSend

接着,直接發送給後端,注意這種類型的發送方式,不能設置請求頭部的Content-Type,應交給瀏覽器來處理(設定Boundary等工做)。

req.send(dataToSend);

text/plain

若是請求頭部沒有設定Content-Type,且數據既不是FormData也不是XML Document(將在xml小節中介紹),則Content-Type默認爲text/plain

這種方式的代碼很簡單,直接發送字符串便可,代碼以下。

req.send('...(此處是字符串格式的數據)');

application/json

JSON格式的數據,後端和各類移動端都很方便處理,用這種MIME類型時,須要將數據對象轉換成JSON串。

首先,轉換數據成JSON串;而後,設定請求頭部的Content-Type,就能夠發數據了。代碼以下。

/* data參數爲表單數據組成的對象 */

req.send( JSON.stringify(data) );

text/xml

目前沒有遇到過要用XML的狀況,大部分均可用JSON代替,爲了完整起見,我也順便總結一下。

首先,構建XML文檔對象,存入表單數據,代碼以下。

/* data參數爲表單數據組成的對象,dataToSend爲待發送給後端的數據 */

var dataToSend = document.implementation.createDocument("", "formdata", null);
var tempData = dataToSend.documentElement;
for (var key in data) {
    if (data.hasOwnProperty(key)) {
        var keyElement = doc.createElement(key);
        keyElement.appendChild(doc.createTextNode(data[key]));
        tempData.appendChild(keyElement);
    }
}

/*
xml文檔格式示意:
<formdata>
    <key1> value1 </key1>
    <key2> value2 </key2>
</formdata>
*/

以後,與multipart/form-data同樣,直接發送數據,不需設置Content-Type

req.send(dataToSend);

小結

  1. multipart/form-datatext/xml不須要設置請求頭的Content-Type

  2. 關於method,以上都是POST方式,如果GET方式是沒有請求數據體的,數據直接加在URL後面;

附:接收請求時的解析方式

  • text/xml:用responseXML

  • application/json:須要先JSON化,JSON.parse( responseText )

  • 其餘:就直接用responseText

jQuery 方式

application/x-www-form-urlencoded

jQuery中默認的表單提交方式,與XMLHttpRequest不一樣的地方在於:數據的URL方式編碼,由jQuery來作,只須要在$.ajax({})參數中設置processData = true(這也是默認,可省略)。

代碼以下。

/* dataToSend爲Object類型的表單數據,不然jQuery會拋出異常 */

$.ajax({
    method: 'POST',
    url: '...',
    data: dataToSend,
    
    contentType: 'application/x-www-form-urlencoded',    // 可省略
    processData: true,        // 可省略

    success: function() {...}
});

注意:若採用GET方式,則將method改成GET便可,不須要在url後面加上數據。

multipart/form-data

這種MIME類型的提交方式,適合用於上傳文件。

首先,對錶單數據構建成FormData的HTML5對象,代碼以下。

/* dataToSend 是FormData對象,可直接做爲數據傳輸到後端 */

var dataToSend= new FormData();      // HTML5對象, IE11如下不支持
for (var key in data) {
    if (data.hasOwnProperty(key)) {
        dataToSend.append(key, data[key]);
    }
}

以後,用$.ajax()方法傳輸數據。
注意:processDatacontentType必須設定爲false,前者是由於避免FormData對象被轉換成URL編碼,後者則是由於須要靠瀏覽器添加multipart/form-data類型的boundary。

$.ajax({
    method: 'POST',
    url: '...',
    data: dataToSend,          // dataToSend 是FormData對象
    
    contentType: false,        // contentType 必須設置爲false
    processData: false,        // processData 必須設置爲false

    success: function() { ... }
});

text/plain

用該類型提交,則直接傳輸字符串。

$.ajax({
    method: 'POST',
    url: '...',
    data: dataToSend,         
    
    contentType: 'text/plain',       
    processData: false,        // processData 設置爲false則不會轉換成URL編碼

    success: function() { ... }
});

application/json

用該類型提交,則傳輸JSON字符串,因此要用函數JSON.stringify()處理表單數據。

/* data 爲表單Object類型的數據 */

dataToSend = JSON.stringify(data);

$.ajax({
    method: 'POST',
    url: '...',
    data: dataToSend,         
    
    contentType: 'application/json',       
    processData: false,        // processData 設置爲false則不會轉換成URL編碼

    success: function() { ... }
});

注意:若後端也返回JSON字符串時,success回調函數裏接受到的數據參數仍爲字符串,須要轉換成Object類型。
(而Angular不須要)

$.ajax({
...
    success: function(data) {
        var jsonData = JSON.parse(data);
        ...
    }
});

text/xml

首先,構建XML文檔對象,存入表單數據,代碼以下。

/* data參數爲表單數據組成的對象,dataToSend爲待發送給後端的數據 */

var dataToSend = document.implementation.createDocument("", "formdata", null);
var tempData = dataToSend.documentElement;
for (var key in data) {
    if (data.hasOwnProperty(key)) {
        var keyElement = doc.createElement(key);
        keyElement.appendChild(doc.createTextNode(data[key]));
        tempData.appendChild(keyElement);
    }
}

/*
xml文檔格式示意:
<formdata>
    <key1> value1 </key1>
    <key2> value2 </key2>
</formdata>
*/

以後,發送數據dataToSend,代碼以下。

$.ajax({
    method: 'POST',
    url: '...',
    data: dataToSend,
    
    contentType: false,    // contentType 可設爲false也可寫成具體的'text/xml'等    
    processData: false,    // processData 必須設爲false
    
    success: function() { ... }
});

AngularJS 方式

application/x-www-form-urlencoded

用這種MIME類型提交表單數據,則須要對錶單數據進行URL編碼,用$.param(data)函數,代碼以下。

$http({
    method: 'POST',
    url: '...',
    data: $.param(dataToSend),
    headers: { 'Content-Type': 'application/x-www-form-urlencoded'}
).success(...);

multipart/form-data

首先,該類型若是要上傳文件,那麼Angular爲了獲取文件,推薦寫成指令。代碼以下。

.directive("fileReader", [function () {
    return {
        restrict: 'AE',
        scope: {
            fileReader: "="        // HTML中的file-reader做爲存放文件對象的變量
        },
        link: function (scope, element) {
            element.bind("change", function (changeEvent) {
                scope.$apply(function () {
                    scope.fileReader = changeEvent.target.files[0];
                });
            });
        }
    }
}])

/* HTML結構以下 */
<input type="file" name="key1" file-reader="formData.file[1]">

而後,須要用FormData對象來包裝表單數據並傳輸,建議寫在$http服務的transformRequest選項中;
另外,與jQuery相似其中的請求頭Content-Type要設置爲undefined。代碼以下。

$http({
    method: 'POST',
    url: '...',
    data: dataToSend,
    headers: {
        'Content-Type': undefined               // 必須設置爲undefined
    },

    transformRequest: function(data) {
        var tempFormData = new FormData();      // HTML5對象, IE11如下不支持
        for (var key in data) {
            if (data.hasOwnProperty(key)) {
                tempFormData.append(key, data[key]);
            }
        }
        return tempFormData;
    }
}).success(...)

text/plain

以字符串的方式提交表單數據,代碼以下。

$http({
    method: 'POST',
    url: '...',
    data: dataToSend,
    headers: {
        'Content-Type': 'text/plain'
    }).success(...)

application/json

以JSON字符串的方式提交表單數據,用JSON.stringify()函數轉換,代碼以下。

$http({
    method: 'POST',
    url: '...',
    data: JSON.stringify(dataToSend),
    headers: {
        'Content-Type': 'application/json'
    }).success(...)

注意:可是在success函數裏接受到的參數,就是Object對象,不須要和jQuery同樣用JSON.parse()轉換。

text/xml

multipart/form-data相似,在transformRequest中構建XML Document,請求頭中的Content-Type設置爲undefinedtext/xml等,代碼以下。

$http({
    method: 'POST',
    url: '...',
    data: dataToSend,
    headers: {
        'Content-Type': undefined               // 設置爲undefined或'text/xml'等
    },

    transformRequest: function(data) {
        var doc = document.implementation.createDocument("", "formdata", null);
        var tempData = doc.documentElement;
        for (var key in data) {
            if (data.hasOwnProperty(key)) {
                var keyElement = doc.createElement(key);
                keyElement.appendChild(doc.createTextNode(data[key]));
                tempData.appendChild(keyElement);
            }
        }
        return doc;
    }
}).success(...)

附:GET方式提交表單數據

Angular用GET方式提交表單數據,應該用$http服務的params而不是data來傳數據,params能夠直接傳入Object類型數據,代碼以下。

$http({
    method: 'GET',
    url: '...',
    params: dataToSend
}).success(...)
相關文章
相關標籤/搜索