1、实现方法

1)form表单提交

为一个下载按钮添加click事件,点击时动态生成一个表单,利用表单提交的功能来实现文件的下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 下载文件
* @param {String} path - 请求的地址
* @param {String} fileName - 文件名
*/
function downloadFile(downloadUrl, fileName) {
// 创建表单
const formObj = document.createElement("form")
formObj.action = downloadUrl
formObj.method = "get"
formObj.style.display = "none"
// 创建input,主要是起传参作用
const formItem = document.createElement("input")
formItem.value = fileName // 传参的值
formItem.name = "fileName" // 传参的字段名
// 插入到网页中
formObj.appendChild(formItem)
document.body.appendChild(formObj)
formObj.submit() // 发送请求
document.body.removeChild(formObj) // 发送完清除掉
}

2)a标签的download

1
2
3
4
5
6
<a href="example.jpg" download>点击下载</a>

<a href="example.jpg" download="test">点击下载</a> // 指定文件名

// 检测浏览器是否支持download属性
const isSupport = 'download' in document.createElement('a');

3)openlocation.href

1
2
3
window.open("downloadFile.zip")

location.href = "downloadFile.zip"

4)Blob对象

调用api,将文件流转为Blob二进制对象,

思路: 发请求获取二进制数据,转化为Blob对象,利用URL.createObjectUrl生成url地址,赋值在a标签的href属性上,结合download进行下载。

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
/**
* 下载文件
* @param {String} path - 下载地址/下载请求地址。
* @param {String} name - 下载文件的名字/重命名(考虑到兼容性问题,最好加上后缀名)
*/
downloadFile (path, name) {
const xhr = new XMLHttpRequest();
xhr.open('get', path);
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function () {
if (this.status === 200 || this.status === 304) {
// 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob
if ('msSaveOrOpenBlob' in navigator) {
navigator.msSaveOrOpenBlob(this.response, name);
return;
}
/*
如果发送请求时不设置xhr.responseType = 'blob',
默认ajax请求会返回DOMString类型的数据,即字符串。
此时需要使用两处注释的代码,对返回的文本转化为Blob对象,然后创建blob url,
此时需要注释掉原本的const url = URL.createObjectURL(target.response)。
*/
/*
const blob = new Blob([this.response], { type: xhr.getResponseHeader('Content-Type') });
const url = URL.createObjectURL(blob);
*/
const url = URL.createObjectURL(this.response); // 使用上面则注释此行
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 上面方法本地测试有时会有跨域问题,下面使用axios重写一下
// 已经配置好proxy
downloadFile (path, name) {
axios.get({
url: path,
method: 'get'
}).then(res => {
const blob = new Blob([res.data], { type: res.headers['content-type'] });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
})
}

该方法不能缺少a标签的download属性的设置。

因为发请求时已设置返回数据类型为Blob类型(xhr.responseType = 'blob'),所以target.response就是一个Blob对象,打印出来会看到两个属性sizetype。虽然type属性已指定了文件的类型,但是为了稳妥起见,还是在download属性值里指定后缀名,如Firefox不指定下载下来的文件就会不识别类型。

文章作者: Mr. Fortunate
文章链接: https://www.fortunate.cool/2022/12/03/%E5%89%8D%E7%AB%AF%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 fortunate

评论