HTML 中 form 表单的 enctype

Preface

最近发现虽然经常使用form表单提交数据,但是对其还是有一点模糊,比如:postput有什么区别,application/x-www-form-urlencodedmultipart/form-data有什么区别,为什么只能通过mutipart/form-data的方式上传文件;所以想花点时间来好好研究一下

Post And Put

说到数据传输,那最常见的就是http请求中的postput方法了,它们都是向server发送数据来操作server的资源;比如非常常见的创建用户和修改用户信息等操作;那它们有什么区别呢?

postput最大的区别就是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

这也是通过表单提交数据的一种方式,只不过传输数据的bodyapplication/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分隔开,并且会在请求的HeaderContent-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/xmlxml文件格式,收到数据就可以按照xml格式去解析

text/xmlapplication/xml的区别在于text/xml 忽略xml文件头中的关于编码的设定,默认采用us-ascii编码,而application/xml会依照xml文件头中编码的设定

还有其他的文本格式,如现在比较常用的:application/json,application/yaml

End

post请求中也可以通过像 XMLHttpRequest 这样的方法在Body中传输任何数据类型;不管什么方式都是需要跟server协商,告诉服务器如何处理

参考:developer.mozilla.org/en-US/docs/…

原文链接:https://juejin.cn/post/7221089899281252411 作者:中等生

(0)
上一篇 2023年4月13日 上午10:21
下一篇 2023年4月13日 上午10:31

相关推荐

发表评论

登录后才能评论