作为一名前端开发者,我们经常遇到下载文件的场景(包括:图片,文档,压缩包等),解决办法五花八门,而且使用场景过于单一...

常规方法

常规方法我们会用a标签或者form表单来实现下载功能。

  • a 标签

a标签的用法都很熟悉,但是却有两个致命缺点:

  1. 不能携带鉴权信息 token

  2. 兼容性问题

image

只有 火狐和谷歌浏览器支持!!!

  • form 表单

form 表单用法很早就有,但是有个明显的缺点:不能修改文件名称

那么需要一个能携带token信息且能修改文件名称还要兼容各大浏览器 怎么结局这个问题呢?本文将为你带来一种 能携带token信息且能修改文件名称还要兼容各大浏览器 的方法!

一生二 二生三 三生万物

核心利于XMLHttpRequesta标签来解决携带 token 信息,利用微软自带的msSaveBlob 方法来兼容IE浏览器

首先能携带token信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
//设置请求头参数的方式,如果没有可忽略此行代码
xhr.setRequestHeader("Authorization",`Bearer ${idToken}`));
//设置响应类型为 blob xhr.open必须为 异步
xhr.responseType = 'blob';
//关键部分
xhr.onload = function (e) {
//如果请求执行成功
if (this.status == 200) {
let blob = this.response;
let a = document.createElement('a');
// blob.type = "application/octet-stream";
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = decodeURIComponent(xhr.getResponseHeader("content-disposition").split(";")[1].split("filename=")[1]);
document.body.appendChild(a); // 火狐浏览器 必须把元素插入body中
a.click();
document.body.removeChild(a);
//释放之前创建的URL对象
window.URL.revokeObjectURL(url);
}
}

然后解决兼容IE浏览器 问题并完善异常捕获

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
30
31
32
33
34
35
36
37
38
39
40
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
//设置请求头参数的方式,如果没有可忽略此行代码
xhr.setRequestHeader("Authorization",`Bearer ${idToken}`));
//设置响应类型为 blob
xhr.responseType = 'blob';
// 关键部分
xhr.onload = function (e) {
// 如果请求执行成功
if (this.status == 200) {
let blob = this.response
let a = document.createElement('a')
// blob.type = "application/octet-stream";
let url = window.URL.createObjectURL(blob)
let fileName = decodeURIComponent(escape(xhr.getResponseHeader('content-disposition').split(';')[1].split('filename=')[1]))
if (window.navigator.msSaveBlob) {
try {
window.navigator.msSaveBlob(blob, fileName)
} catch (e) {
console.log(e)
}
} else {
a.href = url
a.download = fileName
document.body.appendChild(a) // 火狐浏览器 必须把元素插入body中
a.click()
document.body.removeChild(a)
// 释放之前创建的URL对象
window.URL.revokeObjectURL(url)
}
} else { // 失败后需要将blob对象转换为 json 来获取异常信息
const reader = new FileReader();
reader.readAsText(this.response, 'utf-8');
reader.onload = () => {
const { header } = JSON.parse(reader.result);
console.error(header.msg)
}
}
}
xhr.send()

更多前端相关文章:January丶缘