基于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 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请求格式详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • NodeJs form-data格式传输文件的方法

    本文介绍了Node Js 使用KOA处理form-data格式传输过来的文件,分享给大家.具体如下: 使用koa有一段时间了,评价是小巧精悍,只封装了基本的如request对象和response对象到上下文中,其他功能基本上靠第三方中间件来实现.导致的问题是使用起来就不太方便了,比如用koa上传文件,网上资料有限,对于小白而言,文件上传操作就困难多了. form表单上传文件流程(PHP和node js) 文件上传操作原理 form表单[注意:enctype="multipart/form-dat

  • Vue 设置axios请求格式为form-data的操作步骤

    Cover 在Vue中使用axios 这个老生常谈了,还是先记录一遍,方面后面自己查. !!! 设置form-data请求格式直接翻到后面看. 1. 安装axios 在项目下执行npm install axios. 之后在main.js中,添加: import axios from 'axios' //引入 //Vue.use(axios) axios不能用use 只能修改原型链 Vue.prototype.$axios = axios 2. 发送GET请求 axios封装了get方法,传入请求

  • Python发送form-data请求及拼接form-data内容的方法

    网上关于使用python 的发送multipart/form-data的方法,多半是采用 ulrlib2 的模拟post方法,如下: import urllib2 boundary='-------------------------7df3069603d6' data=[] data.append('--%s' % boundary) data.append('Content-Disposition: form-data; name="app_id"\r\n') data.appen

  • 基于form-data请求格式详解

    最近一直都比较忙,坚持月月更新博客的计划不得中止了,今天抽出点时间来说说最近项目中遇到的一个问题,有关request post请求格式中的multipart/form-data格式. 引言 最近在参与一个项目过程中遇到一个问题,相信大部分人都遇到过: 在后端与前端约定好application/json格式传递数据时,因为后台是go强类型语言,在定义api接口时,某些字段要求是整型类型,但是对于前端来说输入框或者从url中的search取到的参数都是字符串,不得不进行前端类型转换. 咋一看,对于接

  • 基于nginx access日志格式详解

    nginx的nginx.cnf中,使用log_format字段可以指定日志的格式文件. log.fromat: log_format access ' [$time_local] | $host | $remote_addr | $request | $request_time | $body_bytes_sent | $status |' '| $upstream_addr | $upstream_response_time | $upstream_status |' ' "$http_ref

  • 基于SpringMVC接受JSON参数详解及常见错误总结

    最近一段时间不想使用Session了,想感受一下Token这样比较安全,稳健的方式,顺便写一个统一的接口给浏览器还有APP.所以把一个练手项目的前台全部改成Ajax了,跳转再使用SpringMVC控制转发.对于传输JSON数据这边有了更深的一些理解,分享出来,请大家指正. 在SpringMVC中我们可以选择数种接受JSON的方式,在说SpringMVC如何接受JSON之前,我们先聊聊什么是JSON.具体的定义我也不赘述了,在JavaScript中我们经常这样定义JSON 对象 var jsonO

  • Java Spring MVC获取请求数据详解操作

    目录 1. 获得请求参数 2. 获得基本类型参数 3. 获得POJO类型参数 4. 获得数组类型参数 5. 获得集合类型参数 6. 请求数据乱码问题 7. 参数绑定注解 @requestParam 8. 获得Restful风格的参数 9. 自定义类型转换器 1.定义转换器类实现Converter接口 2.在配置文件中声明转换器 3.在<annotation-driven>中引用转换器 10. 获得Servlet相关API 11. 获得请求头 11.1 @RequestHeader 11.2 @

  • 基于JavaScript表单脚本(详解)

    什么是表单? 一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法. 表单域:包含了文本框.密码框.隐藏域.多行文本框.复选框.单选框.下拉选择框和文件上传框等. 表单按钮:包括提交按钮.复位按钮和一般按钮:用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作. JavaScript与表单间的关系:JS最初的应用就是用于分担服务器处理表单的责任,打破依赖服务器的局面,尽管目前web和jav

  • python爬虫使用requests发送post请求示例详解

    简介 HTTP协议规定post提交的数据必须放在消息主体中,但是协议并没有规定必须使用什么编码方式.服务端通过是根据请求头中的Content-Type字段来获知请求中的消息主体是用何种方式进行编码,再对消息主体进行解析.具体的编码方式包括: application/x-www-form-urlencoded 最常见post提交数据的方式,以form表单形式提交数据. application/json 以json串提交数据. multipart/form-data 一般使用来上传文件. 一. 以f

  • 基于tomcat配置文件server.xml详解

    1. 入门示例:虚拟主机提供web服务 该示例通过设置虚拟主机来提供web服务,因为是入门示例,所以设置极其简单,只需修改$CATALINA_HOME/conf/server.xml文件为如下内容即可.其中大部分都采用了默认设置,只是在engine容器中添加了两个Host容器. <?xml version="1.0" encoding="UTF-8"?> <Server port="8005" shutdown="SH

  • JS JSOP跨域请求实例详解

    在项目开发中遇到跨域的问题,一般都是通过JSONP来解决的.但是JSONP到底是个什么东西呢,实现的原理又是什么呢.在项目的空闲时间可以好好的来研究一下了. 1.什么是JSONP? 要了解JSONP,不得不提一下JSON,那么什么是JSON? JSON is a subset of the object literal notation of JavaScript. Since JSON is a subset of JavaScript, it can be used in the langu

  • 基于Django的ModelForm组件(详解)

    创建类 from django.forms import ModelForm from django.forms import widgets as wd from app01 import models class 类名(ModelForm): class Meta: model = models.表名 #models中的表名 fields="__all__", # 字段 exclude=None, # 排除字段 widgets=None, # 自定义插件 error_message

  • 基于Jexus-5.6.3使用详解

    一.Jexus Web Server配置 在 jexus 的工作文件夹中(一般是"/usr/jexus")有一个基本的配置文件,文件名是"jws.conf". jws.conf 中至少有 SiteConfigDir 和 SiteLogDir 两行信息: SiteConfigDir=siteconf #指的是存放网站配置文件放在siteconf这个文件夹中,可以使用基于jws.exe文件的相对路径 SiteLogDir=log #指的是jexus日志文件放在log这个

随机推荐