使用JS在下载文件时添加请求头header token信息
各位 JSer,在前端下载一个文件大家应该都不陌生吧,后端同事已经把文件准备好了,我们只需要调接口下载就好了。
通常,我们有一种最常见的方法:window.open(URL),在点击事件的回调里调用就好了,浏览器会为我们下载文件。但是这样存在一些场景无法适配,比如,请求的接口需要你传递 token 或别的认证信息,又或者你们的产品设计不允许在下载时闪现一个新页面。
如此,我们就需要使用 fetch 或者别的 axios 等等,结合 a 标签 来实现 模拟点击下载,这样可以在请求头 header 里带上 token,也不会闪现一个新页面。这里我们以 fetch 为例来实现:
- 首先使用
fetch带上我们的headers token发起请求, - 因为后端返回的是一个文件,我们使用
response.blob()获取Blob对象 - 使用
response.headers.get('Content-Disposition')获取响应头里带的内容信息 - 使用
window.URL.createObjectURL(blob)window 下的方法创建指向这个内容的 URL, - 接下来使用原生 JS 方法创建一个 a 标签,并设置 herf 为刚才的 URL
- 然后我们需要处理文件名,可以使用下面的正则来解析文件名,当然你也可以用自己的方法来解析,响应头的里的内容是可以看到的,你也可以 console 来看,通常后端返回的文件名是没有问题的,但是我们也需要处理一下,如果解析错误,有一个默认的文件名,你可以自己传入,没传入就是 file.txt
- 最后把这个
a 标签插入页面,再执行点击事件就能下载,要记得释放 window 下的这个 URL 对象哦。
export const downloadFileWithFetch = async (URL, token, fileName = 'file.txt') => {
const response = await fetch(URL, {
headers: {
AccessToken: token,
},
});
const blob = await response.blob(); // 获取Blob对象
const contentDisposition = response.headers.get('Content-Disposition');//获取响应头
const url = window.URL.createObjectURL(blob); // 创建一个指向该blob的URL
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
if (contentDisposition) {
// 尝试从Content-Disposition解析文件名
const matches = /"([^"]*)"/.exec(contentDisposition);
if (matches != null && matches[1]) {
a.download = matches[1];
}else{
a.download = fileName
}
}
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url); // 释放URL对象
}