Content-type的作用
content-type
是http
请求头中的一个字段,他用于指示请求体或者响应体数据的MIME
类型
进一步理解就是:web
应用中大部分数据的传输使用的都是http
协议,content-type
用于指示请求和响应中body
传输数据的类型,可以参考chrome devtools
中的network
对于网络请求的分类,如下:
这其中除了WS
代表websocket
,其他网络请求的载体几乎都是http
以js
文件为例:
这里的content-type
说明了该文件是js
文件;
除了js
文件,css
文件,html
文件,图片等也都是通过http
传输,其各自的content-type
区分了各自的类型
这里是针对相应的content-type
进行分类,而fetch
和xhr
请求载体也是http
,但是此时响应的content-type
就不是统一的一种,xhr/fetch
在这里被统一划分成一类
Xhr/Fetch请求的Content-type
对于非ajax
请求,其目的大部分都是为了获取某文件,所以请求方法是get
,而get
请求的请求头没有content-type
,这是因为get
没有请求体,其参数是拼接在url
中的,因此无需content-type
对于
Restful
请求,get,post,put,delete,patch
,其实可以简单理解为区分请求类型的一个字段而已,其本质差别仅仅是一个字段中数据的区别而已,只不过在约定俗成中,将各类型分配了各自的意义。
而ajax
请求,载体是xhr/fetch
,随着http
协议作用的丰富化,往往会有获取之外的更新等操作,因此会有post
等方式
针对前端发起的方式不同,请求的所携带的数据组织方式也不相同,因此通过content-type
进行标注,以供后台进行处理。
不携带请求体的请求
get
、delete
请求的标准用法下,一般不携带请求体,因此标准的get
请求不携带content-type
头
携带请求体的请求
如post
,put
,patch
json
content-type
为application/json
,示例如下
js
fetch('http://localhost:9000', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({a:1})
})
实际发出的请求是这个样子的:
内容被编码成字符串放到请求体中发送
表单
content-type
为application/x-www-form-urlencoded
,示例如下
html
<form action="http://localhost:9000" method="post" >
<input type="text" name="name" value="John">
<input type="text" name="age" value="19">
<input type="submit" value="Upload">
</form>
js
fetch('http://localhost:9000', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'username=John&age=19'
})
以上两者实现的效果是相同的,最后发出的结果是:
多个参数被&
相连接以发送
文件上传的分块表单请求
content-type
为multipart/form - data
该content-type
允许请求体分块传输,常用于上传文件的场景;
分块的多个请求,通过唯一的边界字符串间隔,并且会在content-type
中标明
当表单包含上传文件时,则必须使用
multipart/form - data
当使用FromData
对象构建参数时,content-type
默认使用multipart/form - data
示例:
html
<form action="http://localhost:3000" method="post" enctype="multipart/form - data">
<input type="text" name="username" value="John">
<input type="file" name="avatar" id="avatar">
<input type="submit" value="Upload">
</form>
js
const formData = new FormData();
formData.append('username', 'John');
const fileInput = document.getElementById('avatar');
const file = fileInput.files[0];//获取File对象
formData.append('avatar', file);
fetch('http://localhost:3000', {
method: 'POST',
body: formData
//默认使用multipart/form - data
})
以上两者实现效果相同,最后发送的结果是:
http
响应的content-type
Web应用几乎所有的资源都是通过
HTTP
传输的,包括访问网页看到的内容以及交互的js
文件,当然包括XHR/Fetch
请求;HTTP响应的content-type
囊括了这些内容的所有类型
当访问网页时,率先用到的是html
文件:
当继续加载时,用到的其他文件会逐渐继续通过http
,协议传输过来
得益于打包工具chunk
的划分,实现了这样用到时加载的效果,以此类推,其他文件(css
,图片等)也是这样加载进来的
XHR/Fetch
当使用XHR/Fetch
请求时,后端往往通过json
的方式响应数据
流式下载
content-type
为application/octet-stream
以qq官网下载为例
为二进制流式传输,通常用于文件下载
流式传输相比于
Fetch
到文件的整个二进制再触发下载有很大区别:流式传输无需在内存中存放一整个文件,而是处理和存储传输的小块数据;流式传输可以根据网络状况动态调整传输速率,在网络不稳定或带宽有限的情况下,能够更好地适应等等
非Xhr/Fetch的请求content-type?
对于Web应用需要获取某个文件,例如刚开始加载时候的index.html
,是直接通过get
请求该文件的url
获取到的,类似直接在浏览器的地址栏输入url
一样:两者都是为了获取这个文件。得益于打包软件的chunk和浏览器按需加载,每个资源文件都被划分了一个独特的url
来标识该文件,这和url
的本意统一资源标识符
非常吻合;详见 HTTP的发展和URL含义的拓展:todo
当浏览器拿到该文件后,根据响应的content-type
决定该文件的处理方式,如text/javascript
就存放在本地等待被导入使用,如application/octet-stream
就触发浏览器的下载功能,因此content-type
来标识内容类型是非常关键的
上面说到get
请求不携带请求体,因此这些为了获取文件的get
请求也就不带有content-type
注意:需要区分请求的content-type
和响应的content-type
总结
content-type
是一个非常关键的http
头,对于请求,该属性可以告知服务端如何处理请求体,而对于响应,该属性会告知浏览器应该如何对待返回的数据,丰富的content-type
决定了http
属性的适用性非常广泛,与其相关的url
也不仅限于标识网络上的一个特定资源的符号。
恰如当初HTTP/0.9
刚发布时,为url
取名为统一资源标识符
,人们只认为url
只是标识网络资源,他们也很难想象往后的岁月里HTTP
的发展如此迅速,功能变得如此强大,url
从最开始获取资源也开始拓展到发送、更新、删除如此丰富的含义,这也可能导致了很多人对统一资源标识符
的命名不甚理解
而随着更多新的HTTP
版本的发布,未来Web
应用将会变成什么样子呢?是不是也会突破今天人们对Web
的固有思维呢?
无论如何,技术的更迭绝对是益处更甚的好事,我们不应该因为自己掌握的技术被迭代而感到悲伤,更应该为更合理化的技术更迭而感到开心,学习
永远是人生中应该一直保持的根本,恰如Ai蓬勃发展的今天,以往信息检索被极大简化,我们可以将Ai当作知识渊博的名师,这本应该是好事,而对于取代我们工作的担忧,毕竟今天还没发生呢对吧!
人生大多数的烦恼和悲伤都源于对昨天的悔恨和明天的担忧,但是却一直忽略了最关键的今天