Vue项目开发中,遇到界面下载功能时,前端如何实现将后端返回二进制文件在浏览器自动下载?
一、关键代码:
javascript
export function downloadFile(fileName) {
axios({
method: 'post',
url: process.env.VUE_APP_BASE_API + '/cgi-bin/file',
data: {
'X-Token': getToken(),
method: 'download',
data: {
filename: fileName
}
},
responseType: 'blob'
}).then((res) => {
const blob = new Blob([res.data], { type: 'application/octet-stream;charset=utf-8' }); // 将二进制流转为blob
const a = document.createElement('a');
const url = window.URL.createObjectURL(blob); // 创建新的url并指向file对象或blob对象的地址
a.href = url;
a.download = fileName; // 设置下载文件名
a.style.display = 'none'; //避免数据量过大,下载时间长,看到a标签
document.body.appendChild(a);
a.click();//关键;调用点击事件,(模拟a标签的点击下载效果)
document.body.removeChild(a); // 下载完成移除元素
window.URL.revokeObjectURL(url); // 释放内存
});
}
二、实现逻辑:
首先,整个下载逻辑执行有以下几步:
- 前端发起请求拿到后端返回的二进制格式的数据;
- 将请求响应体中的二进制目标数据转行为blob类型的数据;
- 创建一个
a标签
,后续的自动下载的关键功能就是利用a.click()
实现; - 利用
window.URL.createObjectURL(blob)
方法,利用第二步转换的blob数据创建出一个url,并赋值给第三步创建的a标签的href属性; - 利用
document.body.appendChild(a)
将a标签
添加到body标签
中,后执行a.click()
实现文件下载; - 下载完成后,要移除
a标签
,使用代码document.body.removeChild(a)
实现; - 释放第四步创建的url地址内存;
- 整个下载流程结束。
三、代码解读:
-
如上图,封装了下载文件的函数,其中
axios
网络请求的编写根据你实际后端定的接口来写,主要目的就是拿到后端返回的二进制数据。其中fileName,是当前请求一个参数,同时也作为后续要用到的文件名。需要注意的是,请求的responseType:"blob"
。 -
二进制格式数据转行blob数据类型的代码;
javascript
const blob = new Blob([res.data], { type: 'application/octet-stream;charset=utf-8' }); // 将二进制流转为blob
- 创建a标签;创建url地址;给a标签href属性赋值url地址;执行点击操作;最后移除a标签 释放url内容。
javascript
const a = document.createElement('a');
const url = window.URL.createObjectURL(blob); // 创建新的url并指向file对象或blob对象的地址
a.href = url;
a.download = fileName; // 设置下载文件名
a.style.display = 'none'; //避免数据量过大,下载时间长,看到a标签
document.body.appendChild(a);
a.click(); //关键;调用点击事件,(模拟a标签的点击下载效果)
document.body.removeChild(a); // 下载完成移除元素
window.URL.revokeObjectURL(url); // 释放内存