基于form-data请求格式详解


Posted in Javascript onOctober 29, 2019

最近一直都比较忙,坚持月月更新博客的计划不得中止了,今天抽出点时间来说说最近项目中遇到的一个问题,有关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 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
})

上面创建了一个FormData对象,通过fetch进行ajax请求时,会自动为其将其转为form-data格式,无需手动添加格式。

对象转FormData对象

对于FormDat对象,像上面那种形式可以直接添加参数比较方便,但是对于对象或者嵌套对象:

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

上面形式添加formData参数user,并不会获取到其真正的内容,而是返回userObj的Object.prototype.toString.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) ? '[]' : `[${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请求格式详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
firefox插件Firebug的使用教程
Jan 02 Javascript
javascript call方法使用说明
Jan 11 Javascript
javascript 词法作用域和闭包分析说明
Aug 12 Javascript
jQuery创建平滑的页面滚动(顶部或底部)
Feb 26 Javascript
javascript截取字符串(通过substring实现并支持中英文混合)
Jun 24 Javascript
JQuery实现点击div以外的位置隐藏该div窗口
Sep 13 Javascript
JS日期加减,日期运算代码
Nov 05 Javascript
jQuery表单验证简单示例
Oct 17 Javascript
JavaScript判断浏览器和hack滚动条的写法
Jul 23 Javascript
jQuery实现广告条滚动效果
Aug 22 jQuery
vue实现模态框的通用写法推荐
Feb 26 Javascript
JS+HTML5 canvas绘制验证码示例
Dec 05 Javascript
解决vue-cli项目开发运行时内存暴涨卡死电脑问题
Oct 29 #Javascript
JS操作字符串转数字的常见方法示例
Oct 29 #Javascript
Vue axios 将传递的json数据转为form data的例子
Oct 29 #Javascript
详解Vue 项目中的几个实用组件(ts)
Oct 29 #Javascript
JS操作json对象key、value的常用方法分析
Oct 29 #Javascript
JQuery 实现文件下载的常用方法分析
Oct 29 #jQuery
Vue 设置axios请求格式为form-data的操作步骤
Oct 29 #Javascript
You might like
php变量范围介绍
2012/10/15 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
Apache站点配置SSL强制跳转443
2021/03/09 Servers
根据分辨率不同,调用不同的css文件
2006/08/25 Javascript
编写兼容IE和FireFox的脚本
2009/05/18 Javascript
学习ExtJS fit布局使用说明
2009/10/08 Javascript
JQuery index()方法使用代码
2010/06/02 Javascript
js获取通过ajax返回的map型的JSONArray的方法
2014/01/09 Javascript
用box固定长宽实现图片自动轮播js代码
2014/06/09 Javascript
关于jQuery判断元素是否存在的问题示例探讨
2014/07/21 Javascript
jQuery实现的导航条切换可显示隐藏
2014/10/22 Javascript
node.js中的console.time方法使用说明
2014/12/09 Javascript
测试IE浏览器对JavaScript的AngularJS的兼容性
2015/06/19 Javascript
修改jquery中dialog的title属性方法(推荐)
2016/08/26 Javascript
js数组与字符串常用方法总结
2017/01/13 Javascript
五步轻松实现JavaScript HTML时钟效果
2020/03/25 Javascript
LayUI数据接口返回实体封装的例子
2019/09/12 Javascript
Vue学习笔记之计算属性与侦听器用法
2019/12/07 Javascript
JavaScript函数Call、Apply原理实例解析
2020/02/17 Javascript
python中日期和时间格式化输出的方法小结
2015/03/19 Python
Python随机生成一个6位的验证码代码分享
2015/03/24 Python
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
Django模板变量如何传递给外部js调用的方法小结
2017/07/24 Python
python 调用c语言函数的方法
2017/09/29 Python
Python实现PS滤镜碎片特效功能示例
2018/01/24 Python
Python输出各行命令详解
2018/02/01 Python
Python在cmd上打印彩色文字实现过程详解
2019/08/07 Python
python使用pygame实现笑脸乒乓球弹珠球游戏
2019/11/25 Python
与UNIX有关的几个名词
2015/09/17 面试题
本科毕业生自我鉴定
2013/11/02 职场文书
继承公证书
2014/04/09 职场文书
公司请假条范文
2014/04/11 职场文书
基层党组织整改方案
2014/10/25 职场文书
因工资原因离职的辞职信范文
2015/05/12 职场文书
2015年小学语文教学工作总结
2015/05/25 职场文书
Android开发实现极为简单的QQ登录页面
2022/04/24 Java/Android