基于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 相关文章推荐
dwr spring的集成实现代码
Mar 22 Javascript
JavaScript打字小游戏代码
Dec 26 Javascript
jQuery的缓存机制浅析
Jun 07 Javascript
用JavaScript实现PHP的urlencode与urldecode函数
Aug 13 Javascript
拥有一个属于自己的javascript表单验证插件
Mar 24 Javascript
利用js判断手机是否安装某个app的多种方案
Feb 13 Javascript
Js自动截取字符串长度,添加省略号(……)的实现方法
Mar 06 Javascript
JS解决IOS中拍照图片预览旋转90度BUG的问题
Sep 13 Javascript
Vue中封装input组件的实例详解
Oct 17 Javascript
在 Vue 项目中引入 tinymce 富文本编辑器的完整代码
May 04 Javascript
video.js 一个页面同时播放多个视频的实例代码
Nov 27 Javascript
vue 使用 canvas 实现手写电子签名
Mar 06 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
亚洲咖啡有什么?亚洲咖啡产地介绍 亚洲咖啡有什么特点?
2021/03/05 新手入门
PHP 5昨天隆重推出--PHP 5/Zend Engine 2.0新特性
2006/10/09 PHP
php制作的简单验证码识别代码
2016/01/26 PHP
jQuery 可以拖动的div实现代码 脚本之家修正版
2009/06/26 Javascript
让mayfish支持mysqli数据库驱动的实现方法
2010/05/22 Javascript
从零开始学习jQuery (四) jQuery中操作元素的属性与样式
2011/02/23 Javascript
js结合正则实现国内手机号段校验
2015/06/19 Javascript
JavaScript中的数据类型转换方法小结
2015/10/26 Javascript
原生js实现商品放大镜效果
2017/01/12 Javascript
JavaScript数组迭代方法
2017/03/03 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
2017/06/11 jQuery
JavaScript如何获取到导航条中HTTP信息
2017/10/10 Javascript
mac上配置Android环境变量的方法
2018/07/08 Javascript
vue二级菜单导航点击选中事件的方法
2018/09/12 Javascript
vue  自定义组件实现通讯录功能
2018/09/30 Javascript
Vue源码解析之数据响应系统的使用
2019/04/24 Javascript
taro开发微信小程序的实践
2019/05/21 Javascript
解析原来浏览器原生支持JS Base64编码解码
2019/08/12 Javascript
Vue.js组件通信之自定义事件详解
2019/10/19 Javascript
原生js实现随机点餐效果
2019/12/10 Javascript
[56:00]2018DOTA2亚洲邀请赛 4.6 淘汰赛 VP vs TNC 第二场
2018/04/10 DOTA
和孩子一起学习python之变量命名规则
2018/05/27 Python
破解安装Pycharm的方法
2018/10/19 Python
python实现朴素贝叶斯算法
2018/11/19 Python
Win10下Python3.7.3安装教程图解
2019/07/08 Python
python第三方库学习笔记
2020/02/07 Python
Pretty Little Thing美国:时尚女性服饰
2018/08/27 全球购物
后勤部长岗位职责
2013/12/14 职场文书
2014年教师节演讲稿范文
2014/09/10 职场文书
县委常委班子专题民主生活会查摆问题及整改措施
2014/09/27 职场文书
村干部群众路线整改措施思想汇报
2014/10/12 职场文书
2014年学校总务处工作总结
2014/12/08 职场文书
原来闭幕词是这样写的呀!
2019/07/01 职场文书
八年级地理课件资料及考点知识分享
2019/08/30 职场文书
CocosCreator ScrollView优化系列之分帧加载
2021/04/14 Python
Python竟然能剪辑视频
2021/05/25 Python