首先可以看这一篇《浏览器的下载行为基本原理》
引言
浏览器自动下载zip文件通常是由后端服务提供的接口实现的。后端服务器通过以下步骤来允许下载zip文件:
- 创建zip文件:服务器端根据需求从数据库或文件系统中读取文件,并将这些文件组成一个zip压缩包。
- 设置下载响应头:在发送zip文件之前,服务器会将响应头设置为
Content-Type: application/zip
,并指定Content-Disposition: attachment; filename="yourfile.zip"
,这里的filename
是告知浏览器下载的文件将被保存的名称。 - 返回zip文件:服务器将压缩好的zip文件以HTTP响应形式发送给浏览器。
- 浏览器自动下载:当浏览器接收到这些响应时,它将根据Content-Disposition头部的
attachment
指示自动将文件下载到用户指定的位置。
application/octet-stream
Content-Type: application/octet-stream
是一个 HTTP 头部字段,用于指定传输的数据内容类型。具体来说,application/octet-stream
表示发送的数据是一个二进制流,通常用于文件下载。
以下是 application/octet-stream
的一些关键点:
- 二进制流:
octet-stream
表示数据是一个字节流,这通常用于表示文件内容,而不是文本或 HTML 等文本格式。 - 文件下载:当服务器发送一个文件给客户端时,通常会使用这个
Content-Type
,以便浏览器知道这是一个文件而不是其他类型的数据。 - 浏览器行为:浏览器接收到
application/octet-stream
时,通常会提示用户保存文件而不是尝试显示(预览)它。 - 内容处理:由于数据是二进制的,浏览器不会尝试解释或渲染数据,而是将其作为文件下载处理。
- 安全性:在某些情况下,使用
application/octet-stream
可以减少浏览器执行恶意代码的风险,因为浏览器不会尝试执行或解释这些数据。 - 附件下载:如果响应中包含
Content-Disposition
头部,并且设置为attachment
,浏览器通常会将文件作为附件下载,而不是直接打开。
例如,如果你请求一个 PDF 文件,服务器可能会发送以下头部:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="example.pdf"
这会告诉浏览器这是一个二进制文件,应该被下载并保存为名为 “example.pdf” 的文件。
请注意,尽管 application/octet-stream
通常用于文件下载,但它是一个通用的二进制流类型,可以用于各种类型的二进制数据传输。例如通过axios请求blob二进制流数据。
Content-disposition的含义
Content-Disposition
是一个 HTTP 响应头字段,用于指示浏览器在接收到响应体后应该如何处理内容。这个字段主要用于控制内容的展示方式,尤其是当服务器想要提示用户保存文件而不是直接在浏览器中打开或显示内容时。
Content-Disposition
的值通常是一个指令,后面跟着一个或多个参数。以下是一些常见的指令和参数:
- attachment:
- 这个指令告诉浏览器应该提示用户将响应体保存为文件。通常与一个
filename
参数一起使用,以建议保存的文件名。 - 示例:
Content-Disposition: attachment; filename="example.pdf"
- inline:
- 这个指令告诉浏览器应该在浏览器窗口中直接显示内容,而不是提示用户保存文件。
- 示例:
Content-Disposition: inline; filename="image.png"
- form-data:
- 这个指令用于多部分表单数据(multipart/form-data),在上传文件时使用。
Content-Disposition
可以包含以下参数:
-
filename
:建议的文件名,用于保存文件时使用。 -
filename*
:用于指定非 ASCII 文件名,使用字符集和语言信息。 -
size
:文件的大小(以字节为单位)。
以下是一些 Content-Disposition
的使用示例:
Content-Disposition: attachment; filename="report.pdf"
这会提示用户将响应体保存为名为 “report.pdf” 的文件。
Content-Disposition: inline; filename="image.jpg"
这会尝试在浏览器中直接显示图片。
Content-Disposition: attachment; filename*=UTF-8''%E4%B8%AD%E6%96%87%E6%96%87%E4%BB%B6.pdf
这会提示用户保存文件,文件名为中文“中文文件.pdf”。
请注意,Content-Disposition
只是一个提示,浏览器可以自由地忽略它。例如,某些浏览器可能会忽略 inline
指令,而是默认下载文件。此外,Content-Disposition
不应该用于安全敏感的内容,因为它可以被客户端轻松地绕过。
方式一: a标签直接点击下载静态资源
<a href="https://dev.mysql.com/get/Downloads/MySQLInstaller/mysql-installer-community-8.0.40.0.msi" download>点击下载</a>
此时的浏览器会自动启动他自己的下载管理工具,可以暂停与取消;
方式二: 服务端动态生成的资源进行js点击下载
假如从服务端请求到一打算文本,需要下载
function downloadTxtFile(){
const text = '我爱你';
const element = document.createElement("a");
const file = new Blob([text], {
type: "text/plain",
});
element.href = URL.createObjectURL(file);
element.download = "myFile.txt";
document.body.appendChild(element);
element.click();
}
假如从服务端请获取到的blob二进制进行保存
async function startDownload() {
// get data using axios
let results = await axios({
url: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZ4gbghQxKQ00p3xIvyMBXBgGmChzLSh1VQId1oyhYrgir1bkn812dc1LwOgnajgWd-Yo&usqp=CAU',
method: 'GET',
responseType: 'blob'
})
let hidden_a = document.createElement('a');
hidden_a.href = window.URL.createObjectURL(new Blob([results.data]));
hidden_a.setAttribute('download', 'download_image.jpg');
document.body.appendChild(hidden_a);
hidden_a.click();
}
当然也可以通过axios的onDownloadProgress方法监听进度。
注意:这种模式下在axios数据流传输的空挡浏览器不会认为是在下载。并不是真正意义上的下载,只有前端使用blob进行a链接存储的时候才是真正意义上的下载文件,这个时候浏览器才会弹出文件下载的文件框
Blob
Blob(Binary Large Object)
二进制类型的大对象,其名称来源于SQL数据库,表示一个不可变、原始数据的类文件对象;
在JavaScript
中,它不一定非得是大量数据,其也可以表示一个小型文本文件的内容;
Blob
是不透明的,只能获取它们的大小、MIME类型以及将它们分割成更小的Blob;
构造函数:Blob(blobParts [, options])
:返回一个Blob对象,其内容由参数中给定的数组串联组成;
参数:blobParts
是一个由ArrayBuffer、ArrayBufferView、Blob、String
等对象构成的Array
,或者其他类似对象的混合体,它将会被放入Blob
;其中,Strings
会被编码为UTF-8;options
是一个可选的BlobPropertyBag([bɡ])
字典,它可能会指定如下两个属性:
type
,默认值为""
,它代表了将会被放入到blob中的数组内容的MIME类型;
endings
,默认值为"transparent"
,用于指定包含行结束符\n的字符串如何被写入,
- 它是以下两个值中的一个:
"native"
,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 -
"transparent"
,代表会保持blob中保存的结束符不变