文件下载是前端开发中一个常见的功能,目前主流的下载实现主要有两种:静态文件直接下载和文件流下载
直接下载
顾名思义,直接下载即通过浏览器的文件策略直接下载文件。通常用于下载静态文件。
实现方法
常用的方法即使用a标签或者使用js在浏览器中打开Excel、Word等类型的文件链接,浏览器就会帮我们自动下载这些文件。
存在问题
由于浏览器的策略问题,当文件类型为 pdf 或 jpg 等类型时,浏览器会默认进行预览,即使你设置了 download 属性,大多数浏览器都仍然会执行预览
解决方法
要想直接下载 pdf 或 jpg 之类的文件,就需要了解浏览器的文件策略。浏览器在文件请求中的 Content-Type 中可以获取到文件的类型,比如 pdf 的请求返回的 Content-Type: application/pdf,浏览器判断文件为 pdf ,则会自动执行预览的策略,如果我们在后端代码或nginx中设置其 Content-Type: application/octet-stream 则浏览器将会该文件识别为文件流,自动执行下载操作。 既然了解其原理,那么问题就迎刃而解了,
- 最简单暴力的方法则是直接设置后端或者nginx中 response header 的 Content-Type: application/octet-stream,那么不管什么类型的文件都会自动下载了
# nginx中添加如下配置即可
location /data {
add_header Content-Type 'application/octet-stream;';
}
- 通过一个get请求,将静态文件转换为文件流然后再进行下载
function downloadFile () {
axios({
method: 'get',
url: 'http://127.0.0.1/data/001.pdf',
responseType: 'blob' // 设置返回的数据类型
}).then(res => {
const data = res.data;
downloadBlob(data, '测试.pdf'); // 将返回的数据拼接成文件后下载
})
}
function downloadBlob(content, fileName) {
var blob = new Blob([content]);
if ('download' in document.createElement('a')) {
var elink = document.createElement('a');
elink.download = fileName;
elink.style.display = 'none';
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
}
else { // IE10+下载
navigator.msSaveBlob(blob, fileName);
}
}
文件流下载
文件流下载即通过请求后端接口,接口返回blob类型的数据,前端组装成文件后自行下载即可。一般用于数据文件的导出。
实现方法
文件流下载的实现方法和前文提到的第二种方法基本一致,将接口返回后的数据处理好下载即可。代码见上文。