一、直接下载
针对一些浏览器无法识别的文件格式。可以直接在地址栏上输入URL即可触发浏览器的下载功能。
同类的还有window.location.href、window.open
- 地址栏输入文件URL
- window.location.href = URL
- window.open(URL)
二、首先想到的方案是通过a标签指定href和download属性
实践中发现,这种方式的局限是download属性受同源策略影响,当资源跨域时,download属性失效。结果变成了预览而不是下载,如果第三方配置了CORS则能下载但下载时不能重命名文件。
直接下载仅使用的浏览器无法识别的文件。如果是浏览器支持的文件格式(如:html、jpg、png)等。则不会触发文件下载,而是被浏览器直接触发解析展示。
针对这种情况,我们可以使用a标签的download属性,可以设置文件名。
写法如下:
<a href="/images/download.jpg" download="myFileName">
三、适用于图片下载
// 创建a标签下载
downOption(fileUrl, fileName) {
let link = document.createElement('a');
link.href = fileUrl;
link.target = '_blank';
link.rel = 'noopener norefferrer';
link.download = fileName;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
四、通用的文件下载(适合图片/视频/PDF等等)
以axios为例,或者用xhr也可以
downloadFile({ url, name }) {
axios({
url: url,
method: 'get',
responseType: 'blob'
}).then(res => {
let blob = new Blob([res.data], { type: res.data.type });
let newUrl = URL.createObjectURL(blob);
this.downOption(newUrl, name);
});
}
五、直接下载(后端兼容处理attachment)
有很多场景。有些浏览器可识别的文件格式,我们还是需要直接下载的情况(如:用户直接分享的下载pdf、txt;很多浏览器也是支持展示的)。
这种情况下,我们需要声明一下文件的header的 Content-Disposition信息。告诉浏览器,该链接为下载附件链接,并且可以声明文件名(方式二也可以下载该类型文件,不过文件名会以header设置的文件名优先)。
写法如下:
Content-Disposition: attachment; filename="filename.xls"
六、鉴权下载
在部分场景中,有一些文件,需要用户登录之后根据权限来开放下载(报表等)。
此时,我们需要将本地的用户信息传给服务端。常用的方式如:在header增加token。
这里我们需要使用XmlHttpRequest来想后台发起请求。并带上header信息,获取到文件数据之后,在使用下载方法。
axios示例如下:
axios({
method:'get',
url: '/download/file.doc'
responseType: 'blob',
headers: {
Authorization: '123456'
}
}).then(res => {
let fileUrl = window.URL.createObjectURL(res.data)
iTools.download('filename',fileUrl) // 方法二使用到的a标签download方式。
window.URL.revokeObjectURL(fileUrl)
})