前端文件下载

我心飞翔 分类:javascript

文件流下载

前端通常有两种方式下载:

  1. 后端给一个链接,直接通过 window.open(url)打开即可下载,这种通常适用于这个链接可以在公网访问,不需要token鉴权。
  2. 后端给一个接口,通过传参请求接口,后端返回一个文件流,前端处理文件流,通过a标签下载。

以下代码即是通过文件流下载:

download(url, params, options = {}) {
let { method } = options
method = method ? method : 'get'
let data = method === 'get' ? { params } : { data: params };
return this.request(method, url, data, {
timeout: 0,
responseType: 'blob', // 返回 blob形式文件流
}).then(res => {
let data = res.data // 拿取到 data
let fileReader = new FileReader();
/* onload回调 */
fileReader.onload = function () {
try {
let jsonData = JSON.parse(this.result);
if (jsonData.error_msg) {
// 说明后台返回json数据,有报错信息
Message.error(jsonData.error_msg)
}
} catch (err) {
// 解析成对象失败,说明是正常的文件流,执行下载操作
//设置文件名称
let downloadNameMsg = res.headers['content-disposition'];
let downloadName = downloadNameMsg ? decodeURIComponent(downloadNameMsg.split(";")[1].split("=")[1]) : '自定义文件名.扩展名';
//生成url,以及a节点
let blob = new Blob([res.data]);
let url = window.URL.createObjectURL(blob);
let link = document.createElement('a');
//给节点添加属性
link.style.display = 'none';
link.download = downloadName;
link.href = url;
//渲染节点并触发事件
document.body.appendChild(link);
link.click();
//完成移除节点释放blob
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
};
/* 调用readAsText,传入data 读取数据 注意:这里需要先绑定回调再执行读取数据,否则可能造成数据读取完了还没有绑定上事件*/
fileReader.readAsText(data)
return true;
}).catch(err => {
return false;
})
}

下载流程:

  1. 整理好请求参数,注意:需要返回blob文件流就需要设置 responseType: 'blob'
  2. 发起请求后得到相应的数据。由于我们设置了返回文件流形式,如果后端有报错信息是通过json形式返回的。因此,需要使用FileReader对文件流做处理 ,在onload回调函数中JSON.parse(this.result)能转成功,说明返回的是json格式,也就是报错信息。反之则是正常的文件流,那么执行下载操作
  3. 设置下载文件名:通常文件名都会携带在 headerscontent-disposition 中,通过 split分割获取到文件名
  4. 生成a节点:通过new Blob([res.data])得到文件流,通过window.URL.createObjectURL(blob)创建本地下载链接,然后创建a标签
  5. 设置a标签:将a标签隐藏,通过download属性设置下载名称,href设置下载链接
  6. 将a标签插入到body,并自动执行点击事件
  7. 下载完后,通过removeChild移除a节点,通过window.URL.revokeObjectURL(url)释放 blob

回复

我来回复
  • 暂无回复内容