multipart/form-data
Posted qiqi715
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了multipart/form-data相关的知识,希望对你有一定的参考价值。
目录
- 一.什么是multipart/form-data
- 二.明确在enctype参数为application/x-www-form-urlencoded的时候post和get请求参数和请求体是什么形式的
- 三. multipart/form-data
一.什么是multipart/form-data
首先我们需要明白在html中的enctype属性
.
enctype:规定了form表单在发送到服务器时候编码方式。有如下的三个值。
①application/x-www-form-urlencoded
。默认的编码方式。但是在用文本的传输和MP3等大型文件的时候,使用这种编码就显得 效率低下。
②multipart/form-data
。 指定传输数据为二进制类型
,比如图片、mp3、文件。
③text/plain
。纯文体的传输。空格转换为 “+” 加号,但不对特殊字符编码。
二.明确在enctype参数为application/x-www-form-urlencoded的时候post和get请求参数和请求体是什么形式的
2.1 get请求
请求头:
GET/www.xxx.com?name=%22hello+world%22&**file=temp.png**&submit=submit HTTP/1.1
因为get请求没有请求体,所有他的所有参数都是在url的后边添加。type=file的表单项只能获取到文件的名字,并不能获取文件的内容。
2.2 post请求
请求头:
POST /www.baidu.com HTTP/1.1
请求体:
name=%22hello+world%22&file=temp.png&submit=submit
(1)我们可以发现不管是post请求和get请求,他们的参数存在的形式都是不变的,通过key=value的形式存在。
(2)表单项type=filed只能获取获取文件的名字不能获取文件的内容。
三. multipart/form-data
...
Content-Type: multipart/form-data; boundary=${boundary}
--${boundary}
...
...
--${boundary}--
请求内容格式为Content-Type: multipart/form-data,用来指定请求内容的数据编码格式。
3.1 boundary字符串
该格式会生成一个boundary字符串来分割请求头与请求体的,具体的是以一个boundary=${boundary}来进行分割。
1、上面boundary=${boundary}
之后就是请求体内容了,
2、请求体内容各字段之间以--${boundary}
来进行分割,
3、以--${boundary}--
来结束请求体内容。
3.2 get请求 无效
请求头:
GET/www.xxx.com?name=%22hello+world%22&file=temp.png&submit=submit HTTP/1.1
get请求和multipart/form-data结合无效,因为文件上传需要请求体
。
3.3 post请求:
请求头:
POST /www.xxx.com HTTP/1.1
请求体:
------WebKitFormBoundaryIZDrYHwuf2VJdpHw
Content-Disposition: form-data; name="name"
"hello world"
------WebKitFormBoundaryIZDrYHwuf2VJdpHw
Content-Disposition: form-data; name="file"; filename="temp.png"
Content-Type: image/png
.PNG
.
...
IHDR...
..........Y../..,+|.$aIk.v...G?...P.P,,...m..e.2....v.7. pHYs...%...%.IR$....|IDAT(.cTT....................:.?.......}.(.Pd`A..V...L...?..#.....4.o..LS.....W.d.?...A8..LS...(.u.......D.b......b.....o&..;..<.1......IEND.B`.
------WebKitFormBoundaryIZDrYHwuf2VJdpHw
Content-Disposition: form-data; name="submit"
submit
------WebKitFormBoundaryIZDrYHwuf2VJdpHw--
3.4 多部件请求体
通过观察发现这个的请求体就发生了变化。这种请求体被称之为多部件请求体
。
什么是多部件请求体:就是把每一个表单项分割为一个部件。
因为表单项分为普通表单项
和文件表单项
,所以说部件也有区别。
3.4.1 普通表单项:
- 一个请求头:Content-Disposition: form-data; name=”name”
- 一个请求体:里面就是我们表单的值”hello world”
3.4.2 文件表单项:
- 两个请求头:
- Content-Disposition: form-data; name="file";
- filename="temp.png"
- 一个请求体:
.PNG
.
...
IHDR...
..........Y../..,+|.$aIk.v...G?...P.P,,...m..e.2....v.7. pHYs...%...%.IR$....|IDAT(.cTT....................:.?.......}.(.Pd`A..V...L...?..#.....4.o..LS.....W.d.?...A8..LS...(.u.......D.b......b.....o&..;..<.1......IEND.B`.
------WebKitFormBoundaryIZDrYHwuf2VJdpHw
Content-Disposition: form-data; name="submit"
submit
------WebKitFormBoundaryIZDrYHwuf2VJdpHw--
3.5 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格式,无需手动添加格式。
3.6 对象转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的格式了。
以上是关于multipart/form-data的主要内容,如果未能解决你的问题,请参考以下文章
如何从 WCF 服务返回 multipart/form-data 作为响应
Jersey API 中的 multipart/form-data 出现 CORS 错误
Httpclient multipart/form-data同时发布图片和json
webapi不使用MultipartFormDataStreamProvider上传multipart form-data数据的方法