本系列分为两篇,第一篇总结常用下载方式,不需要认证的文件或者需要认证的小文件下载。第二篇总结的是从需要认证的接口进行大文件下载的几种情况。(分篇依据是从建议使用的维度进行分类,理论上讲,需要认证的几种下载方式也可以进行不需要认证的文件下载)
1. 直接通过获取UrL,利用浏览器跳转页面进行下载(window.open或者模拟点击a标签)
这种方法适用于不需要认证,给我们文件地址就可以直接让浏览器代理下载的情况。但正常项目中的文件,很多需要进行POST请求,接口认证后才能进行文件下载,通常需要在header中添加认证信息,这就无法使用window.open的方式实现了,进而不得不采用流式获取的方式,在js中接收数据。
2. 流式获取,本地内存获取,然后转化为UrL进行下载(createObjectURL)
在需要认证的POST接口中,对于一些小文件,我们通常会先将文件流保存到内存中,等到文件流传输完成,再进行下载。代码如下:
// 使用axios的话
this.$axios.post('http://localhost:3000/download',{
},{
responseType: 'blob'
}).then(function(response) {
const url = window.URL.createObjectURL(new Blob([response.data]));
const a = document.createElement('a');
a.href = url;
a.download = 'helloworld.txt';
a.click();
window.URL.revokeObjectURL(url);
a.remove();
});
// 使用fetch的话
fetch("http://localhost:3000/download",{
method: 'POST',
responseType: 'blob'
}).then(res => {
return res.blob()
}).then(res => {
const blob=new Blob([res])
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'helloworld.txt';
a.click();
window.URL.revokeObjectURL(url);
a.remove();
})
开发过程中遇到两个小知识点
- revokeObjectURL这个方式是用来告知浏览器,通过createObjectURL创建的对象已经可以被清除了。虽然通过垃圾回收机制也可清除,但这个效率更高。
- 使用fetch的时候,fetch有一个很迷惑的配置,mode: 'no-cors',注意使用这个配置的话,他并不是用来解决跨域问题的,如果接口跨域,使用了这个配置,虽然能访问通,但是不会返回任何数据,换句话说,他只能检测接口连通性。
3. 流式获取,通过form进行下载
在不需要header中添加认证的POST请求中,也可以采用form的方式进行下载(比如使用的是cookie认证),他的好处就是下载的时候不会占用js主线程,下载过程中不会导致页面卡顿。当然form也可以直接进行get请求的流式下载(理论上讲,能请求浏览器,就能进行get下载,iframe,form都可以),但这就有点多此一举了,get请求可以直接参考方法1进行下载,省时省力。下面看下如何使用form进行post请求的流式下载。
const form = document.createElement('form')
form.action = "http://localhost:3000/download"
form.target = "_self"
form.method = "post"
form.style.display = "none"
document.body.appendChild(form)
form.submit()
form.remove()
需要注意的是,不管是iframe还是form,进行流式下载的时候,需要服务端在header中添加'Content-Disposition': 'attachment; filename=customfilename.txt'
配置进行强制文件下载,否则会被浏览器当做页面直接进行展示。
以上3个方法常用在不需要认证的下载或者小文件下载。需要认证的大文件下载,请查看总结二。