基于form-data請求格式詳解
最近一直都比較忙,堅持月月更新博客的計劃不得中止了,今天抽出點時間來說說最近項目中遇到的一個問題,有關(guān)request post請求格式中的multipart/form-data格式。
引言
最近在參與一個項目過程中遇到一個問題,相信大部分人都遇到過:
在后端與前端約定好application/json格式傳遞數(shù)據(jù)時,因為后臺是go強類型語言,在定義api接口時,某些字段要求是整型類型,但是對于前端來說輸入框或者從url中的search取到的參數(shù)都是字符串,不得不進行前端類型轉(zhuǎn)換。
咋一看,對于接口參數(shù)比較少的api前端轉(zhuǎn)換沒有什么,但是對于一般的交互復(fù)雜,參數(shù)比較多的接口,要對大部分參數(shù)進行類型轉(zhuǎn)換就是一種吃力不討好的活。好在后端同學(xué)還支持另一種的前后端數(shù)據(jù)交互格式,即multipart/form-data。通過該格式后端取到前端傳遞的數(shù)據(jù)就是數(shù)字了(即使前端傳遞的是字符串),而不像json格式獲取的是字符串。這樣,就不需要額外對前端獲取的數(shù)據(jù)進行特殊轉(zhuǎn)換了。下面就來說說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}--來結(jié)束請求體內(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請求時,會自動為其將其轉(zhuǎn)為form-data格式,無需手動添加格式。
對象轉(zhuǎn)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那樣的方法能批量將對象形式轉(zhuǎn)換為對應(yīng)的形式,formData而言是將對象的key轉(zhuǎn)換為正確formData請求參數(shù)字段名,例如如下對象:
var obj = { a: '2', b: {c: 'test'}, c: [ {id: 1, name: 'xx'}, {id:2 ,name: 'yy', info: {d: 4} } ] }
這樣轉(zhuǎn)換為FormData對象時,其對應(yīng)的key應(yīng)該是下面這樣的:
a: 2 b[c]: test c[][id]: 1 c[][name]: xx c[][id]: 2 c[][name]: yy c[][info][d]:4
這樣,就需要我們自己手動來實現(xiàn)一個轉(zhuǎ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; }
這樣,就可以將對象轉(zhuǎn)化為對應(yīng)的formData的格式了。
以上這篇基于form-data請求格式詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于vue實現(xiàn)網(wǎng)站前臺的權(quán)限管理(前后端分離實踐)
這篇文章主要介紹了基于vue實現(xiàn)網(wǎng)站前臺的權(quán)限管理(前后端分離實踐),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01Vue在頁面右上角實現(xiàn)可懸浮/隱藏的系統(tǒng)菜單
這篇文章主要介紹了Vue在頁面右上角實現(xiàn)可懸浮/隱藏的系統(tǒng)菜單,實現(xiàn)思路大概是通過props將showCancel這個Boolean值傳遞到子組件,對父子組件分別綁定事件,來控制這個系統(tǒng)菜單的顯示狀態(tài)。需要的朋友可以參考下2018-05-05一文搞懂Vue3中的異步組件defineAsyncComponentAPI的用法
這篇文章主要介紹了一文搞懂Vue3中的異步組件,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-07-07vue點擊按鈕跳轉(zhuǎn)到另一個vue頁面實現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue點擊按鈕跳轉(zhuǎn)到另一個vue頁面的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08微信小程序地圖導(dǎo)航功能實現(xiàn)完整源代碼附效果圖(推薦)
這篇文章主要介紹了微信小程序地圖導(dǎo)航功能實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04