浏览器文件下载 | LIXI.FUN
0%

浏览器文件下载

主要原理

前端

1
2
<!-- 其中的 download 提示浏览器下载而不是打开 -->
<a href="http://xxxx.com/yyy.txt" downlod="yyy.txt"></a>

后端

后端的设置主要是为了当浏览不支持 download 属性的时候的兼容性。

1
2
3
res.setContentType("application/octet-stream");
res.addHeaders("Content-Disposition", "attachment;filename=" + filename);
res.addHeaders("Content-Length", content.length);

参考

推荐的 a 标签的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @param {string} url 下载链接
* @param {string} filename 保存到本地的文件名
*/
var fileDownload = function(url, filename) {

var hiddenALink = document.createElement('a');

// 设置下载链接
hiddenALink.href = url;
// 设置保存到本地的文件名
hiddenALink.download = filename;
// 设置在页面上不显示
hiddenALink.style.display = 'none';

// 因为 Firefox 兼容性问题,必须要 append 到页面
document.body.appendChild(hiddenALink);
hiddenALink.click(); // 点击操作
document.body.removeChild(hiddenALink);
}

在 Chrome 中 appendChild(hiddenALink) 的操作可以省去直接 click(),但是在 FireFox 中却不可以,必须要 appendChild() 才可以 click(),具体可参考 stackoverflow programmatical-click-on-a-tag-not-working-in-firefox

优点

  • 简单,直观,方便

缺点

  • 需要传递较多参数时略麻烦
  • 某些情况下的鉴权会不可用

当点击下载,出现的却是 html 文件或者 json 文件的时候,考虑下是不是要放开后端的 security 匿名访问。

ajax 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* 不管是用的原生的 XMLHttpRequest 还是 axios 封装好的
*
* 其最主要的一个点是 responseType: 'blob'
*/
var fileDownload = function(url, filename) {

axios.get(url, {
// 这里可以添加其他参数
// 比如用于筛选数据的,鉴权的
responseType: 'blob'
}).then(res => {
// 此时是已经下载完了的内容
// 如果在下载过程中,没有关于进度的处理,将没有任何提示
// 小文件速度很快,几乎无影响,大文件会有一段儿时间的,无反应等待
// axios 的 res 里的 data 才是 blob 的内容
const content = res.data;

// 这里把下载完的内容,搞成了 ObjectURL
const furl = window.URL.createObjectURL(content);

// 到这里又可以调用上面那个 a 标签的方式了
download0(furl, filename);
})
}

/**
* 这就是上面 a 标签那个
*
* @param {string} url 下载链接
* @param {string} filename 保存到本地的文件名
*/
var download0 = function(url, filename) {

var a = document.createElement('a');

a.href = url;
a.download = filename;
a.style.display = 'none';

document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}

优点

  • 传递参数方便

缺点

  • 超大文件的时候,对客户端的内存不友好
  • 超大文件在页面没有做关于下载进度处理的情况下,看不到下载进度,体验不友好

适用场景

  • 小文件
  • 需要传递较多参数
觉得有收获就鼓励下作者吧