共计 1882 个字符,预计需要花费 5 分钟才能阅读完成。
本文所讲的 POST 请求是 HTTP/1.1 协议中规定的众多 HTTP 请求方法的其中最常用的一个。一般使用 POST 请求方法向服务器发送数据(主要是一些创建更新操作),本文讨论的是 POST 请求方法常用的四种数据提交格式。
由于 HTTP/1.1 协议中并没有对请求使用什么编码方式进行规定,所以理论上开发者完全可以自己决定请求的 Body 体使用什么格式,当然实际上大家都还是用通用的那么几种编码方式来提交数据(生态很关键)。
注:以下排名不分先后。。。
application/x-www-form-urlencoded
对于浏览器原生的 form 表单,enctype 的值不指定的话,默认就是这个家伙。实际上大部分情况都使用它即可,编码方式足够简单高效,各方面支持也都很完备,如各大浏览器调试工具、各大抓包软件等。
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
key1=val1&key2=val2
基本的请求类似上面这样,数据的编码方式采用 key1=val1&key2=val2 的形式,对其中的键值对都需要使用 URL Encode 编码一下。其实就是和 GET 请求的数据提交格式是一样的,只不过位置从 Request URL 上换到了 Request Body 里。
这种格式结构简单,但对于数据层级较深的情况,比如一些有复杂层级关系的接口数据,这种方式就显得有点力不从心了。另一方面,对于需要上传二进制数据(比如图像、音频等文件),这种方式就不那么高效了,而且对于非 ASCII 码的数据就丢失了,所以传文件的情况就不能使用这种方式。
适用场景:数据量不大、数据层级不深的情况下强烈建议这种数据提交格式。
multipart/form-data
当你需要提交文件、非 ASCII 码的数据或者是二进制流数据,则使用这种提交方式。类似下面这个请求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryPAlLG7hJKNYc4ft3
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"
demo
------WebKitFormBoundaryPAlLG7hJKNYc4ft3
Content-Disposition: form-data; name="file"; filename="demo.png"
Content-Type: image/png
------WebKitFormBoundaryPAlLG7hJKNYc4ft3--
第二行指定编码方式 Content-Type 为 multipart/form-data,紧接着生成一个分界线 boundary 即 ----WebKitFormBoundaryPAlLG7hJKNYc4ft3
,又臭又长的目的是为了避免和 Body 正文内容有冲突,它的作用是用来分隔不同的字段。
Body 体分为多个结构类似的部分,每一部分以 --boundary
开头,因为本次请求生成的 boundary 为 ----WebKitFormBoundaryPAlLG7hJKNYc4ft3
,所以最终是 ------WebKitFormBoundaryPAlLG7hJKNYc4ft3
。接着是描述内容的元信息,包括字段名称,如果是文件则还有文件名称和文件类型。接着留一空行,然后才是字段值。什么时候结束呢,以 --boundary--
标志结束。
这种方式本就是专为 上传文件 的场景设计的,虽然你也可以使用这种方式传递普通数据,但无疑会增加不少数据包的大小(这么多 boundary 还是有不少空间占用的)。
适用场景:文件上传。
application/json
很明显在 JSON 格式火之前,肯定没有它的,前面说到使用什么提交数据方式是没有硬性规定的,所以在 JSON 格式火了以后,尤其以其优秀的数据结构表达能力,逐渐流行开来,现在我们对它完全不会陌生。
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"name":"xfly","age": 24, "hobby":["x","xx","xxx"]}
适用场景:数据结构较复杂,层级较深的情况。