提到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
数据类型,当然还有其他的编码格式,但是我暂时还未用到或者见到过。日后使用到其他格式类型,可以继续补充。