提到HTTP使用POST请求提交数据的方式,第一反应就是以对象形式提交,如果是文件,则换成formData形式提交。除此之外好像还有个一长串的x-www-form-urlencoded,可这全是碎片化的知识点,毫无章法。最近做项目时用到了axios,详细的翻看了一下文档,有个地方引起了我的兴趣:By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, you can use one of the following options。等等,这里说axios默认使用序列化的JSON发送数据,但如果你要使用application/x-www-form-urlencoded格式的话,可以使用qs库或者new URLSearchParams()。赶紧网上查阅资料,才发现自己遇到了知识盲点,现系统的总结一下这个小知识点。
概述
常用的HTTP请求方法有GET、POST、PUT、DELETE、HEAD、OPTIONS等。客户端发送一个HTTP请求到服务器,这个请求消息包括:请求行、请求头部、空行和请求数据:
1 | <method> <request-url> <version> |
我们使用POST发送的数据必须放在消息主体(entity-body)中,但是HTTP协议并没有规定使用什么样的编码方式来传送数据。这个编码方式前端可以自己来决定,但是数据发出去,还要服务端能解析成功才有意义。服务端自有不同的方法来解析不同编码格式的数据,而且服务端可以根据请求头(headers)内的Content-Type字段去获知编码方式,然后去解析数据。
几种常见的Content-Type类型
application/x-www-form-urlencoded
application/x-www-form-urlencoded是一种比较常见的编码方式。我们在使用浏览器原生的form表单提交数据时,如果没有指定enctype属性,则默认会以该方式提交数据。
1 | <form action="http://www.baidu.com" method="post"> |
在浏览里可以看到:

首先,我们看到请求头Request Headers内的Content-Type字段被设置为了application/x-www-form-urlencoded;其次,提交的数据按照key1=value1&key2=value2的方式进行了编码,服务端语言对这种编码方式有很好的支持。
multipart/form-data
当我们在上传图片或者文件的时候,会用到这种编码方式。如果使用原生form表单,则需要将enctype设置为multipart/form-data进行提交。如果使用ajax库,则需要以formData的形式提交数据:
1 | let _formData = new FormData(); |
在浏览器中:

首先,请求头内Content-Type除了有multipart/form-data;外,额外生成了一个boundary字段,这个字段用来分割请求数据内的不同字段。在请求体内,数据字段每部分都是以--boundary开头,紧接着是内容描述信息,包括字段名称,字段值等。请求体最后以--boundary—标识结束。
application/json
以application/json作为响应头或者请求头都非常常见。这种编码方式会告诉服务端提交的数据类型是序列化后的JSON字符串,前端在调接口提交数据时,直接以对象形式传递数据即可。
1 | let params = { |
在浏览器端:

axios这个库默认就是使用序列化的JSON形式POST数据。但如果服务器端比较蛋疼的规定只接收application/x-www-form-urlencoded格式,则可以使用qs库或者URLSearchParams API来做转换处理:
1 | const params = new URLSearchParams(); |
写到这里,想到Angular4+同样提供了 HttpParams 类来将普通对象转换为application/x-www-form-urlencoded。当时写Angular的时候还没意识到这一点,真是糊涂。
以上就是平时用到最多的三种POST数据类型,当然还有其他的编码格式,但是我暂时还未用到或者见到过。日后使用到其他格式类型,可以继续补充。