谈谈form-data请求格式js
谈谈form-data请求格式
最近⼀直都⽐较忙,坚持⽉⽉更新博客的计划不得中⽌了,今天抽出点时间来说说最近项⽬中遇到的⼀个问题,有关request post请求格式中的multipart/form-data格式。
引⾔
最近在参与⼀个项⽬过程中遇到⼀个问题,相信⼤部分⼈都遇到过:
在后端与前端约定好application/json格式传递数据时,因为后台是go强类型语⾔,在定义api接⼝时,某些字段要求是整型类型,但是对于前端来说输⼊框或者从url中的search取到的参数都是字符串,不得不进⾏前端类型转换。
咋⼀看,对于接⼝参数⽐较少的api前端转换没有什么,但是对于⼀般的交互复杂,参数⽐较多的接⼝,要对⼤部分参数进⾏类型转换就是⼀种吃⼒不讨好的活。好在后端同学还⽀持另⼀种的前后端数据交互格式,即multipart/form-data。通过该格式后端取到前端传递的数据就是数字了(即使前端传递的是字符串),⽽不像json格式获取的是字符串。这样,就不需要额外对前端获取的数据进⾏特殊转换了。下⾯就来说说form-data。
form-data请求格式
multipart/form-data是基于post⽅法来传递数据的,并且其请求内容格式为Content-Type: multipart/form-data,⽤来指定请求内容的数据编码格式。另外,该格式会⽣成⼀个boundary字符串来分割请求头与请求体的,具体的是以⼀个boundary=${boundary}来进⾏分割,伪码如下:
...
Content-Type: multipart/form-data; boundary=${boundary}
--${boundary}
...
...
--${boundary}--
上⾯boundary=${boundary}之后就是请求体内容了,请求体内容各字段之间以--${boundary}来进⾏分割,以--${boundary}--来结束请求体内容。具体可以参考下⾯例⼦:
POST ample HTTP/1.1js的基本数据类型
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
})
上⾯创建了⼀个FormData对象,通过进⾏ajax请求时,会⾃动为其将其转为form-data格式,⽆需⼿动添加格式。
对象转FormData对象
对于FormDat对象,像上⾯那种形式可以直接添加参数⽐较⽅便,但是对于对象或者嵌套对象:
let userObj = {userName: ’xxx', age: '21'}
formData.append('user', userObj)
上⾯形式添加formData参数user,并不会获取到其真正的内容,⽽是返回userObj的String.call(userObj)的值作为user字段的值。
------WebKitFormBoundaryyb1zYhTI38xpQxBK
Content-Disposition: form-data; name="user"
[object Object]
遗憾的是,FormData对象没有像JSON.stringify那样的⽅法能批量将对象形式转换为对应的形式,formData⽽⾔是将对象的key转换为正确formData请求参数字段名,例如如下对象:
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
这样,就需要我们⾃⼰⼿动来实现⼀个转换数据函数,具体代码如下:
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) ? '[]' : [</span><span class="hljs-subst"><span class="hljs-string"><span class="hljs-subst">${property}</span>];
if(namespace) {
formKey = namespace + key;
} else {
formKey = property;
}
<span class="hljs-comment"><span class="hljs-comment">// if the property is an object, but not a File, use recursivity.</span>
<span class="hljs-keyword"><span class="hljs-function"><span class="hljs-title">if</span>(</span><span class="hljs-keyword"><span class="hljs-function"><span class="hljs-params"><span class="hljs-keyword">typeof</span> obj[proper      objectToFormData(obj[property], fd, formKey);
} <span class="hljs-keyword"><span class="hljs-keyword">else</span> {
<span class="hljs-comment"><span class="hljs-comment">// if it's a string or a File object</span>
fd.append(formKey, obj[property]);
}
}
}
return fd;
}
这样,就可以将对象转化为对应的formData的格式了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。