四种常见的 POST 提交数据方式

按说今天是农历新年开工第一天,我们公司很人性化的多给我们放一天假(然后很不人性化的连上8天班…)

话说昨天终于弄懂了 Postman 里面post 的时候有几种可选择数据格式分别代表什么了,这里简单记录一下

HTTP 报文格式

每一个http报文都包含下面的三个结构:状态行、请求头、消息主体,类似于这样

1
2
3
4
<method> <request-URL> <version>
<headers>
<entity-body>

在使用 POST/PUT 时,协议规定数据必须放在主体(entity-body)中,理论上主体中的数据编码方式完全可以由开发者自己决定,通过请求头(headers)中的 Content-Type 字段向服务器告知,主体中使用的是何种编码,下面介绍四种常见的数据编码

application/x-www-form-urlencoded

这是浏览器的原生 <form> 的默认数据编码格式,效果类似于这样:

1
2
3
4
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

Content-Type 被指定为 application/x-www-form-urlencoded, 提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码

multipart/form-data

当需要用表单提交文件时,我们会把 <form>enctype 设置为 multipart/form-data,此时主体编码方式就变为 multipart/form-data,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST HTTP/1.1
Host: www.demo.com
Cache-Control: no-cache
Postman-Token: 679d816d-8757-14fd-57f2-fbc2518dddd9
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="key"
value
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="testKey"
testValue
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="imgFile"; filename="no-file"
Content-Type: application/octet-stream
<data in here>
------WebKitFormBoundary7MA4YWxkTrZu0gW--

首先请求头中的Content-Type 是multipart/form-data,然后指定一个随机字符串,作为主体中各数据间的分隔符,也就是我们看到的 boundary=xxxx,接着每个数据以 --xxxx 开始,紧接着换行,下面是内容描述信息,接着换2行,接着是数据内容,接着换行,然后以 --xxxx--结尾,最后换行

文本数据和文件,图片的内容描述是不相同的
文本参数:

1
2
3
Content-Disposition: form-data; name="key"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

文件参数:

1
2
3
Content-Disposition: form-data; name="imgFile"; filename="no-file"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

每个换行都是 \r\n

application/json

这个类型可以说是目前 Restful api 使用的主流类型了

1
2
3
4
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title":"test","sub":[1,2,3]}

设置 Content-Type 为 application/json,内容使用 JSON 格式

text/xml

这种类型说实话我不太了解,工作中好像很少使用,从网上复制了一段描述:它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。典型的 XML-RPC 请求是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>

XML-RPC 协议简单、功能够用,各种语言的实现都有。它的使用也很广泛,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服务等等。JavaScript 中,也有现成的库支持以这种方式进行数据交互,能很好的支持已有的 XML-RPC 服务。不过,我个人觉得 XML 结构还是过于臃肿,一般场景用 JSON 会更灵活方便。