el's blog

A noder, FEer. use express, vue...etc

POST提交的三种表单类型简介
Content-type 中 application/x-www-form-urlencoded 和 multipart/form-data 和 application/json 的区别

简介

在和小伙伴对接的时候,围绕数组数据传递我们产生了一些争执,于是我耐下心再去找了一下表单格式的资料。

假定要传递的数据格式为以下一个 Js 对象

1
2
3
4
5
{
num: 4,
str: 'test, test',
arr: [1,2,3]
}

application/x-www-form-urlencoded

窗体数据被编码为名称/值对。这是标准的编码格式。在发送前编码所有字符(默认)。

需要设置 request header 中的 Content-Type: application/x-www-form-urlencoded,查看 postman 中发出去的请求头和数据内容变成以下格式

1
2
3
4
5
6
7
POST /py/api/classrooms/1/trainings HTTP/1.1
Host: 112.124.109.3:8080
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: c7f6dcf3-f78c-b874-c944-6faabdb3b13a
arr=%5B1%2C2%2C3%5D&str=test%2C+test&num=4

提交的数据经由qs这个库序列化后,在chrome下展示的是 Form Data,并且数据将会被显示为

1
2
3
4
5
6
7
8
9
Form Data
{
num: 4,
str: test, test
arr[0]: 1,
arr[1]: 2,
arr[3]: 3,
}

后台接到这种格式 arr,却是不太容易把它当成数组。

multipart/form-data

窗体数据被编码为一条消息,页上的每个控件对应消息
中的一个部分。不对字符编码,这种格式一般用于带上传功能的表单,数据包裹并被 boundary 分割。

查看 postman 中发出去的请求头和数据内容变成以下格式,注意 Content-Type 字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /py/api/classrooms/1/trainings HTTP/1.1
Host: 112.124.109.3:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Cache-Control: no-cache
Postman-Token: a5497708-c791-a09b-aca7-47d9b6b150e2
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="arr"
[1,2,3]
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="str"
test, test
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="num"
4
------WebKitFormBoundary7MA4YWxkTrZu0gW--

application/json

text/plain 类似,提交的是原数据,空格转换为 “+” 加号,但不对特殊字符编码。

查看 postman 中发出去的请求头和数据内容变成以下格式,注意 Content-Type 字段

1
2
3
4
5
6
7
8
9
10
11
POST /test HTTP/1.1
Host: 112.124.109.3:8080
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 87808356-8aa9-adfd-4e15-e4434ba4509d
{
"arr": [1,2,3],
"str": "test, test",
"num": 4
}

在chrome下展示的是 Request Payload

1
2
3
4
5
6
7
Request Payload
{
"arr": [1,2,3],
"str": "test, test",
"num": 4
}

结论

如果约定传 Form Data,也就是 application/x-www-form-urlencoded头,则数组和对象只能转为字符串后,后端经过一层解析来读取。

如果约定传 request payload,也就是 application/json头,则数组和对象随便传递,后端接到的也就是未经处理过的原数据。

而文件上传才用 multipart/form-data