文件下载
文件下载方式
前端涉及到的文件下载还是很多应用场景的,那么前端文件下载有多少种方式呢?每种方式有什么优缺点呢?下面就来一一介绍。
a 标签
定义与用法
- 首先实现
download功能,条件必须满足:所要下载的文件与js或当前页面同源。即window.location.protocol(传输协议)+window.location.host(域名)必须有,且一致; - 如果是本地文件,请启动本地服务,使用
localhost访问页面; - 通过
a标签的download属性来实现文件下载;download 为 h5 中新增的 a 标签属性;download+href 使 a 标签具备点击下载功能; download属性也可以设置一个值来规定下载文件的名称;若没有设置拓展名,浏览器将自动检测正确的拓展名 (.img,.png、.pdf);
兼容性测试及结果
- 代码
1 | <a href="./imgs/cs.jpg">同源图片,不带download</a> |
1 | function down(url) { |
- pc 端浏览器兼容性
总结
- html 不支持的文件,无论同源还是不同源,有没有 download 属性,都会下载。
- html 支持的文件,同源且有 download 属性,除 ie 外都会下载。
- html 支持的文件,不同源,无论有无 download 属性,都不会下载,浏览器会直接跳转打开。
Blob 对象
场景:后端返回给前端
文件流,前端通过Blob下载;文件流格式如下:
Blob 对象
下面是 blob 对象的定义,来自 MDN:
Blob对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成ReadableStream来用于数据操作。
Blob表示的不一定是JavaScript原生格式的数据。File接口基于Blob,继承了blob的功能并将其扩展以支持用户系统上的文件。
blob 对象是 html5 新增的对象,它的作用是用来存储二进制数据的,比如图片、视频、音频等,它的使用方法如下:
1 | /** |
这里主要关注的是 type 属性,默认情况下,blob 对象是没有 type 属性的,那么这个 Blob 就是一个无类型的 Blob,文件不会损毁,但是无法被正常识别。
URL.createObjectURL
下面是 blob 对象的定义,来自 MDN:
URL.createObjectURL () 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的 URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的 URL 对象表示指定的 File 对象或 Blob 对象。
这个方法是用来创建一个 url 的,它的作用是把一个 blob 对象转换成一个 url,这个 url 可以用来下载文件,也可以用来预览文件,代码如下:
1 | const url = URL.createObjectURL(blob) |
这里需要注意的是,这个 url 的生命周期和创建它的窗口中的 document 绑定,也就是说,当我们的 document 被销毁后,这个 url 就会失效,会自动释放它们,但是为了获得最佳性能和内存使用状况,我们应该在安全的时机主动释放掉它们,代码如下:
1 | URL.revokeObjectURL(url) |
下载文件流
指定返回数据格式
首先指定返回数据格式为 blob:
responseType: 'blob'
1 | // 导出报表 |
响应头 headers 获取文件信息
在响应数据
response.headers["content-disposition"]中获取文件信息;包含文件名和文件类型;如下图所示:
可以在响应拦截器里面做数据处理:
- 中文转码了,转回去;
- 将文件信息存到缓存,调用下载接口的时候获取文件信息;(给 a 标签的 download 设置文件名)
1 | //接收到响应数据并成功后的一些共有的处理 |
调用下载接口
- 我们可以打印一下 res,是一个 Blob 对象;(如果接口没有设置 responseType: ‘blob’,这里是后端返回的文件流)
1 | getMeetRoomExport(this.exportParams).then((res) => { |
- 接口请求
这里和后端商量是
docx类型的文件,所以type值如下所示,其他类型的type值设置可参考 MDN;
1 | getMeetRoomExport(this.exportParams).then((res) => { |
至此,文件就会下载成功;
IE 兼容
IE 浏览器是不支持 download 属性的,Internet Explorer 10 的 msSaveBlob 和 msSaveOrOpenBlob 方法允许用户在客户端上保存文件。
用法:
- msSaveBlob:只提供一个保存按钮
1 | window.navigator.msSaveBlob(blobObject, [name]); |
- msSaveOrOpenBlob:提供保存和打开按钮
1 | window.navigator.msSaveOrOpenBlob(blobObject, [name]); |
- 兼容 IE 的下载
1 | getMeetRoomExport(this.exportParams).then((res) => { |
下载拓展
回到我们刚才下载的问题,我们是通过
blob对象来解决,但是我们的type属性是写死的,如果在文件类型是确定的情况下是没问题的,但是如果这个接口就是下载文件的接口,文件可能是各种类型的,我们应该怎么处理?
- 和接口提供者进行协商,确定下载的文件的格式,然后前端将
type写死; - 通过枚举和响应头
response.headers["content-disposition"]来实现;
枚举方式
- 新建 config 写入 blobType 的对象
1 | export const blobType = { |
- 引入,通过缓存中的文件名后缀确定 type 值;大致思路如下:
1 | // 1.引入枚举 |
Blob 拓展
不仅是后端传来的文件流可以下载,字符串、对象、数组等任意类型都可以下载;
1 | // 下载txt格式的文件; |
现象:点击按钮,下载名为 fsl.txt 文件,内容为 “使用 Blob 对象下载文件”;
URL.createObjectURL 拓展
使用 URL.createObjectURL 实现图片本地预览
这个方法是用来创建一个 url 的,它的作用是把一个 blob 对象转换成一个 url,这个 url 可以用来下载文件,也可以用来预览文件;
1 | <body> |























