使用umi-request a标签下载同域链接时不带Cookie的问题
今天Ant design Pro项目上遇到了这个问题,有个需求是后端提供下载链接,可以是提供用户下载查看设备的配置文件。
按常规来说,一般的下载链接是不会做请求鉴权的,但是后端同事说这种配置文件算是隐私了,所以就要做鉴权请求,不提供链接复制到哪都能下载的情况,必须是登录的用户才能下载。
由于后端使用cookie-session模式做的鉴权,并且前端使用是的umi-request做http请求库,使用<a href="url">下载</a>
做链接下载发现请求头没有像其他请求一样自动带上cookie了,所以下载不了。
然后通过查资料,就写了:
/** Request 网络请求工具 更详细的 api 文档: https://github.com/umijs/umi-request */
import request from '@/utils/request';
... //其他代码
const download = async (url) => {
// url = "http://192.168.252.80:43002/v1/device/backup/subDeviceRelations.txt"
const { data, response } = await request(url, {
method: 'get',
getResponse: true,
responseType: 'blob',
});
if (response.ok) {
var blob = data;
var filename = url.split('/').pop(); // 获取链接最后一节当文件名 = "subDeviceRelations.txt"
var a = document.createElement('a');
//创键临时url对象
var url = URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
//释放之前创建的URL对象
window.URL.revokeObjectURL(url);
}
}
return (
<span>
{value ? <a
key='download'
href='#'
onClick={() => {
download(value);
}}
>
下载
</a> : <div>无</div>}
</span>
);
... //其他代码
这种方法是可以解决的,但是有个问题,就是点击下载后就必须等到接口请求完成后才有响应并且弹出浏览器(火狐)默认弹框,询问是否保存的文件,这种弊端就是如果要下载一个超级大的文件,那就用户点击相当于没有响应一样,过了很久才能弹窗。
所以必须想办法找新的解决方案,于是:
return (
<span>
{value ? <a
key='download' // value = "http://192.168.252.80:43002/v1/device/backup/subDeviceRelations.txt"
href={value.substring(value.indexOf(':43002/') + 6)} // href = "/v1/device/backup/subDeviceRelations.txt"
download // 必须设置,要不然直接在浏览器上显示文件内容了
>
下载
</a> : <div>无</div>}
</span>
);
这样href='/v1/device/backup/subDeviceRelations.txt'
umi-repuest底层请求就会自动补充host和cookie了,解决了鉴权问题;还有也能够按照浏览器标准的方式下载文件了,会自动添加显示到浏览器的下载显示转态与进度那里。
参考文章
https://www.jianshu.com/p/f087cdf57846
https://blog.csdn.net/wangjinju77777/article/details/119651652
https://blog.p2hp.com/archives/8105