(一)前置知识

开始前,我们先来复习一下HTTP的基础知识。

HTTP请求分为:请求行、请求头、空行、请求体(也叫正文、请求实体、请求主体)。

HTTP响应分为:状态行(也叫响应行)、响应头、空行、响应体(也叫正文、响应实体、响应主体)。

在HTTP请求中,最常见的GET请求是没有请求体的(GET的查询字符串不属于请求体),只有POST、PUT请求有请求体。

在HTTP响应中,大部分时候都会有响应体,什么情况会没有呢?

状态码为1xx、204 No Content、301、302重定向、304 Not Modified的响应。还有一个,就是HEAD方法的响应,HEAD和GET的区别,是只返回头部信息,不返回实体数据。

我们今天要讨论的HTTP中文件相关的字段,就是指的请求体和响应体(统称为实体)相关的字段。

(二)请求体和响应体相关的字段

1. 数据类型:实体的MIME类型。

Accept:请求头字段,标记客户端可理解的MIME类型,写法如:Accept: text/html,application/xml,image/webp。

Content-Type:通用字段,请求头和响应头都可以用,只要有实体数据,就应该设置正确的Content-Type,没有的话就不需要。Content-Type的数据格式是:数据类型+字符集,比如:application/json;charset=UTF-8。作为请求头时,一般不需要后面的字符集。作为响应头时,当响应体为文本类型时,应该指定字符集。

2. 编码类型:实体的压缩格式,比如gzip, deflate, br。服务器可以通过对数据进行压缩,来减小响应数据的大小。

Accept-Encoding:请求头字段,标记客户端支持的压缩格式,写法如:Accept-Encoding: gzip, deflate, br。

Conent-Encoding:响应头字段,响应体的实际压缩格式,写法如:Content-Encoding: gzip。

3. 语言类型,指的是实体的自然语言,比如汉语、英语等。

Accept-Language:请求头字段,标记客户端可理解的自然语言,写法如:Accept-Language: zh-CN, zh, en。

Content-Language:响应头字段,响应体的实际自然语言,写法如:Content-Language: zh-CN。

4. 字符集,指的是实体的字符集。

Accept-Charset:请求头字段,写法如:Accept-Charset: gbk, utf-8。

这儿要注意,没有对应的响应头字段,响应体的数据类型和字符集,都在Content-Type响应头中。

5. 资源处理方式

Content-Disposition:响应头字段,指示客户端应以何种方式处理响应体数据,是显示(inline)还是下载附件(attachment),写法如:Content-Disposition: attachment; filename="example.pdf"。

6. 数据长度

Content-Length:通用字段。不管对于客户端还是服务端,知道明确的Content-Length,都是有好处的。响应头中的Content-Length更为常见,因为它可以帮助客户端优化加载速度、判断响应是否完整以及何时可以安全关闭连接。

7. 分块传输和范围请求

Transfer-Encoding、Range、Accept-Ranges、Content-Range这些暂不讨论。

有的字段,我们在平时的开发中几乎没用过,感知不到它们的存在,原因很可能是:浏览器和现代框架,会帮助我们自动处理。

我们来重点说一下:Content-Type。

(三)Content-Type请求头:

Content-Type请求头最常用的三个值是:application/x-www-form-urlencoded、multipart/form-data、application/json。还有一些其他值,比如text/plain、text/xml、application/octet-stream等,一般是在发送特定数据格式时使用,用的不多。

application/x-www-form-urlencoded和multipart/form-data这两位起源于HTML表单提交,后来在ajax请求中继续沿用。application/json则是从ajax时代开始流行。所以早期的ajax库如jquery,默认的post数据格式是application/x-www-form-urlencoded,而现代ajax库如axios,默认的数据格式就变成了application/json。

1.application/x-www-form-urlencoded:

这是form表单的默认post提交方式,将字段名和值进行URL编码,得到这种格式:a=1&b=2&c=3。你一定感觉很熟悉,没错,和url的查询字符串长一个样。这种提交方式适用于简单的文本数据,同样也是jquery.ajax的默认post请求方式。

2.multipart/form-data:

当需要上传文件时,不管是通过表单提交,还是各种ajax框架,都需要使用这种提交方式。因为这种格式能够携带二进制数据,比如文件。

3.application/json:

现代ajax框架,普遍默认采用这种post方式,比如axios,它post请求的默认数据格式就是这个。

(四)Content-Type响应头:

相比请求头主要是3个值,Content-Type响应头的值就丰富多了,浏览器根据响应体的数据类型,来做出不同的处理。

比如最常见的网页是text/html,api接口数据是application/json,图片是image/jpeg, image/png, image/gif,css文件是text/css等。

这里面比较特别的就是application/octet-stream,意思是不明类型的二进制数据,浏览器对它的处理方式一般是直接下载。

在nodejs中,如果使用原生的http模块,你需要手动设置Content-Type。但如果使用web框架,比如Express、koa2,如果你不设置,它们会根据内容自动推断并设置一个合适的Content-Type。在nginx等HTTP服务器中,也是会自动添加静态文件的Content-Type,它们内部通常有一张mime类型和文件扩展名的映射表。

(五)文件下载

我们来专门说一下文件下载:

我们工作中大多数HTTP请求,浏览器对于文件的处理方式,都是打开或直接使用,而不是下载。前端和后端,分别可以通过各自的方式来让浏览器下载文件。

1. 前端使用<a href="文件URL" download="自定义文件名">下载文件</a>,只要给a标签添加download属性,就无需管响应头的Conent-Type是什么,都可以点击下载文件,还可以指定下载的文件名。

2. 后端把Content-Type响应头设为:application/octet-stream。这种方式,实际上是把文件标记为不明类型的二进制数据,浏览器通常采用下载的方式处理这种数据。

3. 后端设置正确的Content-Type响应头,然后设置Content-Disposition: attachment; filename="example.pdf"。

Content-Disposition是专门指示浏览器如何处理响应体的内容,被浏览器显示(inline)还是作为附件下载(attachment)。可以看出,Content-Disposition是专门处理文件下载的,这才是服务端指定文件下载的最佳实践。

(六)文件上传

再来说一下文件上传,在web开发中,文件上传经历了从传统表单提交到使用AJAX技术的演变。

表单时代,我们通过<form method="post" enctype="multipart/form-data">来上传文件。

在前端,出于安全考虑,JS没有文件系统的权限,所以我们无法通过编程的方式创建文件,<input type="file" />是唯一的文件获取方式。

我们选中的文件,在JS中就是File对象。文件上传,就是把File对象通过表单提交或ajax发送给后端。

那么ajax时代,我们已经很少使用表单了,上传文件应该怎么写呢?

先考一下你,File对象可以作为一个普通对象的属性值吗?

答案是:不可以。因为对象的属性和值都必须是可序列化的数据,比如简单类型或对象,而File或Blob不是简单可序列化的数据。也就是说,JSON和键值对都不支持二进制数据,只有multipart/form-data这种数据格式支持。

我曾经以为,可以通过这种把File挂在普通对象的方式,作为post的请求的参数,来上传文件。由于以上的原因,这样是行不通的。

现在我们一般很少用表单了,如何存放二进制数据呢?此时我们需要一个新的数据结构:FormData。

FormData是HTML5引入的一个API,它允许我们将表单数据以键值对的形式组织起来,并且可以方便地添加文件内容,它可以模拟表单提交。具体这么写:

// XHR上传文件

// 获取文件输入元素
var fileInput = document.getElementById('fileInput');
var file = fileInput.files[0]; // 创建XMLHttpRequest实例
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/upload', true);
xhr.onload = function () {
if (xhr.status === 200) {
console.log('文件上传成功:', xhr.responseText);
} else {
console.error('文件上传失败:', xhr.statusText);
}
}; // 设置请求头,对于文件上传,通常不需要手动设置Content-Type
// 因为在使用FormData时,浏览器会自动设置
// xhr.setRequestHeader('Content-Type', 'multipart/form-data'); // 创建FormData对象
var formData = new FormData();
formData.append('file', file); // 发送请求
xhr.send(formData);
// axios上传文件

// 获取文件输入元素
var fileInput = document.getElementById('fileInput');
var file = fileInput.files[0]; // 创建FormData对象
var formData = new FormData();
formData.append('file', file); // 使用axios上传文件
axios.post('/api/upload', formData, {
// axios会自动处理FormData的Content-Type
// 无需手动设置
})
.then(response => {
console.log('文件上传成功:', response.data);
})
.catch(error => {
console.error('文件上传失败:', error);
});

以上是对HTTP请求头和响应头中实体字段的总结,重点说明了Content-Type以及文件下载和上传。

这一次,弄明白JS中的文件相关(二):HTTP请求头和响应头的更多相关文章

  1. Cookie和Session在Node.JS中的实践(二)

    Cookie和Session在Node.JS中的实践(二) cookie篇在作者的上一篇文章Cookie和Session在Node.JS中的实践(一)已经是写得算是比较详细了,有兴趣可以翻看,这篇是s ...

  2. js中ajax如何解决跨域请求

    js中ajax如何解决跨域请求,在讲这个问题之前先解释几个名词 1.跨域请求 所有的浏览器都是同源策略,这个策略能保证页面脚本资源和cookie安全 ,浏览器隔离了来自不同源的请求,防上跨域不安全的操 ...

  3. js中scroll滚动相关

    js中scroll滚动相关 scroll,滚动,一般讨论的是网页整体与浏览器之间的关系. 一.元素相关 属性/方法 解释 element.scrollHeight 返回元素的整体高度. element ...

  4. Http消息头中常用的请求头和响应头

    作为Web开发对常用http的请求头和响应头熟悉了解一下还是很有必要的.比如请求头中Content-type指定了请求的内容,若类型是application/x-www-form-urlencoded ...

  5. Head First Python-Python中与文件相关的操作-读、处理、写

    最近在看head first python,前面也写了一些笔记,但是基本上没有涉及到一些完整的代码,现在将书中的文件相关操作的代码整理,供以后参考. 主要分为两大部分,读取文件.处理异常,处理文件.存 ...

  6. HTTP中的请求头和响应头属性解析

    HTTP中的请求头和响应头属性解析 下面总结一下平时web开发中,HTTP请求的相关过程以及重要的参数意义 一次完整的HTTP请求所经历的7个步骤 说明:HTTP通信机制是在一次完整的HTTP通信过程 ...

  7. JavaScript中的this详解(彻底弄懂js中的this用法)!

    要想学好js,那么其中那些特别令人混淆迷惑的知识点,就一定要弄清楚.this关键字就是其中让初学者比较迷惑的知识点之一,不过灵活运用this可以提升代码的性能和复用性,那么今天我就和大家一起来了解th ...

  8. 深入理解JS中的对象(二):new 的工作原理

    目录 序言 不同返回值的构造函数 深入 new 调用函数原理 总结 参考 1.序言 在 深入理解JS中的对象(一):原型.原型链和构造函数 中,我们分析了JS中是否一切皆对象以及对象的原型.原型链和构 ...

  9. 在Node.js中使用RabbitMQ系列二 任务队列

    在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心 ...

  10. JS中如何处理多个ajax并发请求?

    js中的多并发处理. 通常 为了减少页面加载时间,先把核心内容显示处理,页面加载完成后再发送ajax请求获取其他数据 这时就可能产生多个ajax请求,为了用户体验,最好是发送并行请求,这就产生了并发问 ...

随机推荐

  1. 第三方登录--QQ登录--单体应用

    从零玩转第三方QQ登录 下面有源码 前后端分离版本 一样的思路 https://www.cnblogs.com/Yangbuyi/p/13194007.html 第三方GITEE登录 https:// ...

  2. SQLServer清空数据库日志

    -------SQl2008以上 清空日志-------- USE[master] GO ALTER DATABASE [数据库名称] SET RECOVERY SIMPLE WITH NO_WAIT ...

  3. puppeteer的简单使用

    引言 对于编写应用程序,尤其是要部署上线投入生产使用的应用,QA是其中重要的一环,在过去的工作经历中,我参与的项目开发,大多是由测试同学主要来把控质量的,我很少编写前端方面的测试代码,对于测试工具的使 ...

  4. vscode 启动go

    { "version": "0.2.0", "configurations": [ { "name": "La ...

  5. 在线编辑Word——插入公式

    在Word中可插入多种公式,用于满足于不同运算场景需求,从基本的运算符到大型的运算公式,我们可以根据文档内容的编排需要,任意插入所需公式.下面,介绍如何通过在线编辑Word的方式,向Word中插入公式 ...

  6. 介绍3种ssh远程连接的方式

    摘要:SSH(安全外壳协议 Secure Shell Protocol,简称SSH)是一种加密的网络传输协议,用于在网络中实现客户端和服务端的连接,典型的如我们在本地电脑通过 SSH连接远程服务器. ...

  7. 华为云数据治理生产线DataArts,让“数据‘慧’说话”

    摘要:数据治理生产线DataArts改变了传统"人拉肩抗"的数据处理方式,帮助提升效率:降低技术门槛,让"人人都是分析师":让"数据'慧'说话&quo ...

  8. 再获信通院权威认证,优等生华为云GaussDB数据库凭什么?

    摘要:在八大项测试中,华为云 GaussDB的两款数据库都以优异的成绩通过.那么这两款数据库究竟是凭借什么获此殊荣呢? 近期,中国信通院公布了第十三批数据库产品基础能力.性能和稳定性评审结果.在本次评 ...

  9. 总结vue3 的一些知识点:Vue.js 安装

    Vue.js 安装 1.独立版本 我们可以在 Vue.js 的官网上直接下载 vue.min.js 并用 <script> 标签引入. 下载 Vue.js 2.使用 CDN 方法 以下推荐 ...

  10. 7z压缩测试

    注意: CompressionLevel 选择