前言:在一个vue项目开发过程中, 遇到了一个跨域下载文件的功能, 记录一下踩过的坑。
场景:在开发过程中, 遇到一个上传下载的功能, 由于是把文件放到腾讯云上的, 所以当下载的时候会出现跨域的问题.
后台返回数据如下:
filename
线上文件名 (为了防止重复发生文件覆盖问题, 后台将上传的文件重命名)full_url
文件的线上链接mime
文件的 Content-Type 类型original_name
文件上传时的本地命名
采坑过程:
1.由于当时未知跨域问题, 直接使用了 超链接 下载
<div
class="item"
v-for="(item, ind) in taskDetailData.art_files"
:key="ind"
>
<a :href="item.full_url" :download="original_name">
<div class="item_text">{{ item.original_name }}</div>
<div class="icon_box">
<icon icon="download"></icon>
</div>
</a>
</div>
测试结果:
可以看到,rar
类型,xlsx
文件都能下载下来, 可是text
类型,filename
, 并不是我们想要的original_name
所以, 超链接下载不是我们想要的
- 使用
axios
并且转化为Blob
发送请求进行下载
<div
class="item"
v-for="(item, ind) in taskDetailData.art_files"
:key="ind"
>
<a @click="handleDownload(item.full_url, item.original_name, item.mime)">
<div class="item_text">{{ item.original_name }}</div>
<div class="icon_box">
<icon icon="download"></icon>
</div>
</a>
</div>
import axios from "axios";
methods: {
handleDownload(url, fileName, mime) { // 下载附件
axios.get(url, { responseType: 'blob' })
.then(res => {
let blob = new Blob([res.data], { type: mime })
// 注: mime类型必须整正确, 否则下载的文件会损坏
if (window.navigator && window.navigator.msSaveOrOpenBlob) { // 兼容IE
window.navigator.msSaveOrOpenBlob(blob, element.original_name);
} else {
let downloadElement = document.createElement('a');
downloadElement.href = window.URL.createObjectURL(blob); // 创建一个DOMString
downloadElement.download = fileName;
downloadElement.click();
window.URL.revokeObjectURL(blob); // 释放 DOMString ,解除内存占用
}
})
.catch(error => {
console.error(error)
})
}
}
测试结果:下载成功, 什么类型都可以下载, 文件名字也是我们想要的.
总结
由于文件放在腾讯云上, 所以这是跨域下载, 由于安全性的问题, 浏览器是不允许跨域下载的, 所以我们需要先把需要下载的文件获取下来在本地转化为 Blob
二进制流, 再进行下载就没有了跨域的问题