基于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 相关文章推荐
javascript入门·图片对象(无刷新变换图片)\滚动图像
Oct 01 Javascript
jquery easyui combox一些实用的小方法
Dec 25 Javascript
JavaScript变量声明详解
Nov 27 Javascript
JS实现动态增加和删除li标签行的实例代码
Oct 16 Javascript
easyui datagrid 大数据加载效率慢,优化解决方法(推荐)
Nov 09 Javascript
ES6新特性之模块Module用法详解
Apr 01 Javascript
Node.js利用debug模块打印出调试日志的方法
Apr 25 Javascript
纯js实现图片匀速淡入淡出效果
Aug 22 Javascript
利用JS hash制作单页Web应用的方法详解
Oct 10 Javascript
JavaScript适配器模式详解
Oct 19 Javascript
this在vue和小程序中的使用详解
Jan 28 Javascript
vue 解决data中定义图片相对路径页面不显示的问题
Aug 13 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 Mssql操作简单封装支持存储过程
2009/12/11 PHP
PHP的autoload自动加载机制使用说明
2010/12/28 PHP
php在线解压ZIP文件的方法
2014/12/30 PHP
smarty模板引擎使用内建函数foreach循环取出所有数组值的方法
2015/01/22 PHP
PHP给前端返回一个JSON对象的实例讲解
2018/05/31 PHP
PHP创建对象的六种方式实例总结
2019/06/27 PHP
使Ext的Template可以解析二层的json数据的方法
2007/12/22 Javascript
在chrome浏览器中,防止input[text]和textarea在聚焦时出现黄色边框的解决方法
2011/05/24 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
2015/04/03 Javascript
使用jspdf生成pdf报表
2015/07/03 Javascript
深入理解Javascript中的自执行匿名函数
2016/06/03 Javascript
在vue-cli搭建的项目中增加后台mock接口的方法
2018/04/26 Javascript
Vuex实现数据共享的方法
2019/12/20 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
Vue3 实现双盒子定位Overlay的示例
2020/12/22 Vue.js
[39:02]DOTA2亚洲邀请赛 3.31 小组赛 B组 Mineski vs VGJ.T
2018/04/01 DOTA
Python中的yield浅析
2014/06/16 Python
Python中字典和JSON互转操作实例
2015/01/19 Python
Python中decorator使用实例
2015/04/14 Python
python 异常处理总结
2016/10/18 Python
Python基于回溯法子集树模板解决数字组合问题实例
2017/09/02 Python
Python实现二维数组输出为图片
2018/04/03 Python
Python 中的range(),以及列表切片方法
2018/07/02 Python
python3.7.0的安装步骤
2018/08/27 Python
HTML5实现视频直播功能思路详解
2017/11/16 HTML / CSS
html5 canvas fillRect坐标和大小的问题解决方法
2014/03/26 HTML / CSS
爱他美官方海外旗舰店:Aptamil奶粉
2017/12/22 全球购物
linux面试题参考答案(8)
2015/08/11 面试题
大四毕业生学习总结的自我评价
2013/10/31 职场文书
英语专业学生的自我评价
2013/12/30 职场文书
销售演讲稿范文
2014/01/08 职场文书
运动会入场解说词
2014/02/07 职场文书
2014全国两会学习心得体会1000字
2014/03/10 职场文书
2014年库房工作总结
2014/11/26 职场文书
2019脱贫攻坚工作总结报告范本!
2019/08/06 职场文书
浅谈:电影《孔子》观后感(范文)
2019/10/14 职场文书