前言
首先要知道下载的链接是一个静态文件还是二进制流,静态文件指的是服务器上就放了一个文件,你访问的是文件存放的路径,二进制流就是由后端一边读取(或者一边生成)一边传文件。
二者的区别为:静态文件可以通过a标签的download直接下载,二进制流则需要获取后转成文件对象再用a标签下载
a标签使用静态链接直接下载
使用场景为链接已知(但是后端要做好防盗链)
<a href="下载的链接" download="文件名(也可不写默认为静态文件的文件名)"></a>
js动态获取链接下载
使用场景为
1、动态获取链接之后才下载
2、要传一点参数给后端
3、后端生成短期静态链接后返回
4、后端使用minio之类的文件系统
优点:
1、可以传参数
2、链接是有时效性的,安全性好(临时文件的情况)
缺点:
1、会有一个loading的过程之后才会下载
// 调用api示例,返回一个url
await url= await Api.getDownloadUrl({
data: { something }
});
function jsDownload(url){
// 生成一个a标签
var a = document.createElement('a');
document.body.appendChild(a);
// 如果是完整的链接
a.href = url;
// 如果只是返回了后半段的链接
// a.href = location.origin + url;
// 静态文件的话不一定会生效,所以后端要把名字起好
a.download = '文件名'+'.xls';
// 触发点击
a.click();
// 用完就删掉,避免越加越多
document.body.removeChild(a);
}
js异步二进制流下载
需要设置 responseType: ‘blob’
先介绍一下 new Blob
new Blob(参数一,参数二)
参数一是数组,传入二进制流数据
参数二是对象,可以设置blob的文件类型
如下接收excel
const blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'});
type类型很多,需要的什么类型再去搜索
// 以 axios为例,其它的插件也差不多,这里主要讲收到之后怎么处理
axios.get(url,{
responseType:'blob',
}).then(res => {
downloadFile(res.data)
})
// 转化为blob对象下载
function downloadFile(data){
const blob = new Bolb([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'})
// 把blob对象转成一个可下载的链接;注意:window.URL或者URL都行
let url = URL.createObjectURL(blob);
jsDownload(url);
// 下载完记得删掉链接,延时更保险;4E4就是40秒
setTimeout(function () { URL.revokeObjectURL(url) }, 4E4)
}
为什么有些博客写下载文件加了FileReader?
FileReader是js读取文件的API,在下载文件使用的时候,作用跟URL.createObjectURL是一样的,都是为了生成a标签能下载的链接,但是它跟URL.createObjectURL的区别就是,URL.createObjectURL苹果不兼容(苹果一堆的兼容问题要处理,宛如智障)
// 下面的代码只是示意,要做兼容用后面介绍的file-saver.js
var reader = new FileReader()
reader.onloadend = function () {
var url = reader.result
url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;')
jsDownload(url)
}
reader.readAsDataURL(blob)
使用file-saver.js
file-saver很简单,总共就100多行代码,就是上面方法的集合,做了兼容处理。推荐使用它
使用方式
import FileSaver from 'file-saver';
var blob = new Blob([data], {
type: 'text/plain;charset=utf-8',
});
FileSaver.saveAs(blob, '文件名.csv');
// 也可以script标签引入使用
<script src="http://purl.eligrey.com/github/FileSaver.js"></script>
// 然后它会挂载在window上
window.saveAs();
一些建议
- 浏览器打开的页面,二进制流用file-saver下载
- app里面打开的页面使用静态地址,因为很可能会下载不了
- app里面下载,最好还是由app开发提供jsapi给你调用原生app的下载方法(兼容性最佳)