Preface
最近发现虽然经常使用form
表单提交数据,但是对其还是有一点模糊,比如:post
和put
有什么区别,application/x-www-form-urlencoded
和multipart/form-data
有什么区别,为什么只能通过mutipart/form-data
的方式上传文件;所以想花点时间来好好研究一下
Post And Put
说到数据传输,那最常见的就是http
请求中的post
和put
方法了,它们都是向server
发送数据来操作server
的资源;比如非常常见的创建用户和修改用户信息等操作;那它们有什么区别呢?
post
和put
最大的区别就是put
操作是幂等的,也就是不管你操作几次结果都是一样的;而post
则不是幂等的,post
的操作是要在服务器上创建资源的;比如:创建用户,如果操作两次就会报错:“user already exist”,而对user
的多次put
操作都会是一样的结果(一般不会强制要求patch
的幂等性)
Post Content-Type
我们经常会使用HTTP
协议中的Post
方法向服务器提交数据,实现对指定资源的操作;并且会在请求的Header
中使用Content-Type
字段指定将要传输的数据类型;服务器在收到请求之后,根据Content-Type
接收客户端发送的数据,然后实现相应的逻辑
在http
请求中,使用Post
方法的发送数据的常见的方式有如下三种Content-Type
:
application/x-www-form-urlencoded
multipart/form-data
text/plain
不同的Content-Type
表示不同的数据表现形式,服务器器接收的方式也就会有所不同,下面我们详细讨论一下方式
Content-Type:application/x-www-form-urlencoded
这种是表单提交数据时默认的类型,提交的数据在请求体中,格式是用&
分隔的键值对,如下:
key1=val1&key2=value2
如果在key
或者value
中有非字母,数字的字符就会对其进行URL编码,这也就是为什么它不适合传输二进制数据的原因了
下面是一个使用该类型发送请求的例子,前端代码如下:
<body>
<form action="test.php" method="post">
<input type="text" name="name" placeholder="Name">
<input type="text" name="email" placeholder="Email">
<input type="submit" name="submit" value="Submit">
</form>
</body>
我们使用Post
方法向服务器发送用户名和邮箱,下面是发送的请求体:
POST / HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
name=admin&email=11%40qq.com
在上面的例子中可以看到,如果发送的数据包含非字母数字的就会被进行转义;它的数据传输方式和查询参数的很类似,如果使用post
方式,这些数据就是放在请求体中进行传输,而如果是使用get
方法,那么这些参数就会作为查询参数传输,如下:
http://www.example.com?name=admin&email=11%40qq.com
传输参数的编码方式都一样,只不过一个在Body
当中,另外一个在url
中
Content-Type:multipart/form-data
这也是通过表单提交数据的一种方式,只不过传输数据的body
和application/x-www-form-urlencoded
不太一样;multipart/form-data
是将要传输的数据分成多个部分,每一个部分作为一个单独数据块,并指定该部分中要传输数据的Content-Type
,每两个数据块之间使用一个分隔符来区分(分隔符是由请求方来指定)
下面通过一个例子来看下multipart/form-data
的数据是如何被发送的,以及具体的格式;前端代码如下:
<form action="test.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="text" name="username" />
<input type="submit" value="Upload" />
</form>
下面是发送的请求体,
POST / HTTP/1.1
Host: www.example.ai
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryQa8xYdWftN9gXLbb
Content-Length: 560
------WebKitFormBoundaryQa8xYdWftN9gXLbb
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: application/octet-stream
<test.txt>
------WebKitFormBoundaryQa8xYdWftN9gXLbb
Content-Disposition: form-data; name="username"
admin
------WebKitFormBoundaryQa8xYdWftN9gXLbb--
请求的每一个部分都是用boundary
分隔开,并且会在请求的Header
中Content-Type
告诉服务器此次请求的请求体分为多个部分(multipart
),每两个部分之间的boundary
为----WebKitFormBoundaryQa8xYdWftN9gXLbb
,这样服务器拿到body
之后就知道如何提前数据了
multipart/form-data
更加适合向服务器发送二进制数据,所以在向服务器发送文件的时候,经常就会用到这种类型;而如果只是向服务器提交key/value
值的时候,那么不建议使用这种方式,因为其boundary
会增加网络负载
Content-Type:text/plain
text/plain
表示客户端发送的内容纯文本格式,也就是说是一种无格式的内容,服务器在接收到数据之后需要做相应的转化去适应自己的程序;比如:
POST /text HTTP/1.1
Content-Type: text/plain
User-Agent: PostmanRuntime/7.28.3
Accept: */*
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 15
This is a test!
当然,在text/plain
的基础上也有很多的扩展格式,比如:text/html
将文件标识为html
文件,浏览器在收到之后就会将其按照html
格式进行解析,text/xml
是xml
文件格式,收到数据就可以按照xml
格式去解析
text/xml
和application/xml
的区别在于text/xml
忽略xml
文件头中的关于编码的设定,默认采用us-ascii
编码,而application/xml
会依照xml
文件头中编码的设定
还有其他的文本格式,如现在比较常用的:application/json,application/yaml
等
End
在post
请求中也可以通过像 XMLHttpRequest 这样的方法在Body
中传输任何数据类型;不管什么方式都是需要跟server
协商,告诉服务器如何处理
原文链接:https://juejin.cn/post/7221089899281252411 作者:中等生