前端根据url实现文件下载

往常开发过程中,文件下载的实现都是后端提供一个接口,大多是返回一个Blob对象,然后前端编码实现下载,在这次项目中后端只返回文件的url,需要自己实现下载,突然发现自己连这么基础的问题都解决不了,确实挺离谱的。

通过Blob对象下载

先前说了,往常是通过后端返回一个Blob对象来实现下载功能,如果后端返回的是二进制的文件流,我们需要指定ajax请求的响应类型为blob

先看下后端返回Blob的情况下应该怎么实现下载呢。

1
2
3
4
5
6
7
8
9
10
async downloadFn(){
// 一个虚假的请求,res就是后端返回的Blob对象,方便后续演示
let res = await downLoad(params)
let file_name = '文件名称'
let save_blob = new Blob([res])
let save_link = document.createElement('a')
save_link.setAttribute('href', window.URL.createObjectURL(save_blob))
save_link.setAttribute('download', file_name)
save_link.click()
}

就这么简单,关键点就是new BlobcreateObjectURL

注意点是new Blob([data])中的data只能是ArrayBuffer、blob等几种类型,不是所有类型都可以直接放入的。

如果后端不直接返回blob,而是一个文件流,那么需要指定接口的响应类型,其他就同后端直接返回blob一样了

1
2
3
4
5
6
7
8
9
// 请求接口
getFile(){
return axios({
method: 'post',
url: '',
data: '',
responseType: 'blob'
})
}

通过Url实现下载

我们在只有一个url的情况下,我最开始通过简单的a标签想实现这个功能,但是并不是那么可行的。

查阅网上前辈的解决方法,找到了一个学习成本最低的,就是我们通过这个url来得到一个Blob对象,然后就跟前边一样了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
downloadFile(url){
let file_name = '文件名称'
let url2 = url.replace(/\\/g, '/')
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
// 指定响应类型
xhr.responseType = 'blob';
// 为了避免大文件影响用户体验,建议加loading
xhr.onload = () => {
if (xhr.status === 200) {
// 获取文件blob数据并保存
saveAs(xhr.response, fileName);
}
};
xhr.send();
}
saveAs(data, name){
const urlObject = window.URL || window.webkitURL || window;
const export_blob = new Blob([data]);
// 如果要下载excel文件,可以传入配置项(xls格式)
// const export_blob = new Blob([data],{type: "application/vnd.ms-excel"})
// 如果要导出.xlsx格式的文件将type更改为:
// application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
// 如果可以尽量使用xlsx格式
const save_link = document.createElement('a')
save_link.href = urlObject.createObjectURL(export_blob);
save_link.download = name;
save_link.click();
}

这个方法呢是先去请求这个url,并将返回的内容格式设置为blob,然后就是一样的new BlobcreateObjectURL了。

作者

胡兆磊

发布于

2021-12-29

更新于

2022-10-23

许可协议