溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于form-data請求格式詳解

發(fā)布時間:2020-08-23 19:13:19 來源:腳本之家 閱讀:366 作者:wonyun 欄目:web開發(fā)

最近一直都比較忙,堅持月月更新博客的計劃不得中止了,今天抽出點時間來說說最近項目中遇到的一個問題,有關request post請求格式中的multipart/form-data格式。

引言

最近在參與一個項目過程中遇到一個問題,相信大部分人都遇到過:

在后端與前端約定好application/json格式傳遞數(shù)據(jù)時,因為后臺是go強類型語言,在定義api接口時,某些字段要求是整型類型,但是對于前端來說輸入框或者從url中的search取到的參數(shù)都是字符串,不得不進行前端類型轉換。

咋一看,對于接口參數(shù)比較少的api前端轉換沒有什么,但是對于一般的交互復雜,參數(shù)比較多的接口,要對大部分參數(shù)進行類型轉換就是一種吃力不討好的活。好在后端同學還支持另一種的前后端數(shù)據(jù)交互格式,即multipart/form-data。通過該格式后端取到前端傳遞的數(shù)據(jù)就是數(shù)字了(即使前端傳遞的是字符串),而不像json格式獲取的是字符串。這樣,就不需要額外對前端獲取的數(shù)據(jù)進行特殊轉換了。下面就來說說form-data。

form-data請求格式

multipart/form-data是基于post方法來傳遞數(shù)據(jù)的,并且其請求內(nèi)容格式為Content-Type: multipart/form-data,用來指定請求內(nèi)容的數(shù)據(jù)編碼格式。另外,該格式會生成一個boundary字符串來分割請求頭與請求體的,具體的是以一個boundary=${boundary}來進行分割,偽碼如下:

...
Content-Type: multipart/form-data; boundary=${boundary} 

--${boundary}
...
...

--${boundary}--

上面boundary=${boundary}之后就是請求體內(nèi)容了,請求體內(nèi)容各字段之間以--${boundary}來進行分割,以--${boundary}--來結束請求體內(nèi)容。

具體可以參考下面例子:

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryyb1zYhTI38xpQxBK

------WebKitFormBoundaryyb1zYhTI38xpQxBK
Content-Disposition: form-data; name="city_id"

1

------WebKitFormBoundaryyb1zYhTI38xpQxBK
Content-Disposition: form-data; name="company_id"

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

PNG ... content of chrome.png ...
------WebKitFormBoundaryyb1zYhTI38xpQxBK--

form-data格式一般是用來進行文件上傳的。使用表單上傳文件時,必須讓

表單的 enctype 等于 multipart/form-data,因為該值默認值為application/x-www-form-urlencoded。

FormData對象

XMLHttpRequest Level 2添加了一個新的接口FormData。利用FormData對象,我們可以通過JavaScript用一些鍵值對來模擬一系列表單控件,我們還可以使用XMLHttpRequest的send()方法來異步的提交這個"表單"。

var formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456); 
fetch('/users', {
 method: 'POST',
 body: formData
})

上面創(chuàng)建了一個FormData對象,通過fetch進行ajax請求時,會自動為其將其轉為form-data格式,無需手動添加格式。

對象轉FormData對象

對于FormDat對象,像上面那種形式可以直接添加參數(shù)比較方便,但是對于對象或者嵌套對象:

let userObj = {userName: 'xxx', age: '21'} formData.append('user', userObj)

上面形式添加formData參數(shù)user,并不會獲取到其真正的內(nèi)容,而是返回userObj的Object.prototype.toString.call(userObj)的值作為user字段的值。

------WebKitFormBoundaryyb1zYhTI38xpQxBK
Content-Disposition: form-data; name="user"

[object Object]

遺憾的是,F(xiàn)ormData對象沒有像JSON.stringify那樣的方法能批量將對象形式轉換為對應的形式,formData而言是將對象的key轉換為正確formData請求參數(shù)字段名,例如如下對象:

var obj = {
  a: '2', 
  b: {c: 'test'}, 
  c: [ 
    {id: 1, name: 'xx'}, 
    {id:2 ,name: 'yy', info: {d: 4} }
  ]
}

這樣轉換為FormData對象時,其對應的key應該是下面這樣的:

a: 2
b[c]: test
c[][id]: 1
c[][name]: xx
c[][id]: 2
c[][name]: yy
c[][info][d]:4

這樣,就需要我們自己手動來實現(xiàn)一個轉換數(shù)據(jù)函數(shù),具體代碼如下:

function objectToFormData (obj, form, namespace) {
 const fd = form || new FormData();
 let formKey;
 
 for(var property in obj) {
   if(obj.hasOwnProperty(property)) {
    let key = Array.isArray(obj) ? '[]' : `[${property}]`;
    if(namespace) {
     formKey = namespace + key;
    } else {
     formKey = property;
    }
   
    // if the property is an object, but not a File, use recursivity.
    if(typeof obj[property] === 'object' && !(obj[property] instanceof File)) {
     objectToFormData(obj[property], fd, formKey);
    } else {
     
     // if it's a string or a File object
     fd.append(formKey, obj[property]);
    }
    
   }
  }
 
 return fd;
  
}

這樣,就可以將對象轉化為對應的formData的格式了。

以上這篇基于form-data請求格式詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI