之前暑假和团队一起做了一个仿百度云盘的系统,涉及到文件的下载,预览等等,都不需要携带token。想想其实这种设计是不合理的。但是当时由于技术水平不高,所以只能采取不加控制的文件操作。但是在新的任务中,给的接口就是要求headers中携带token,然后后台返回文件流,折腾了一番终于80%上实现了这个功能。
- 首先讲讲不需要token验证的文件下载前端怎么实现
原理其实非常简单,利用a标签
<a href="url" download="name"></a>
解释一下,a标签href里放置文件的地址,这个地址是文件在服务器上存储的地址。
假如在服务器端有一个专门的文件服务器,那么这个地址就是文件实际上在文件服务器中存储的地址。
download其实可加可不加,表示文件的名称。不加就是文件的默认文件名
当点击a标签的时候,文件的下载过程,转码等等操作是由浏览器来自主完成的,浏览器能自动检测文件扩展名来生成对应的文件格式。
- 然后讲讲需要token验证的文件下载前端怎么做
首先是有两种方法的
第一种,还是使用a标签。在请求的正确返回里构造一个a标签
this.$axios.get('/xxxxx')
.then(res => {
var btn = document.createElement("a");
btn .setAttribute('download', '');// download属性
btn .setAttribute('href', '');// href链接
abtn click();// 自执行点击事件
})
由此可见,这种方法的关键在于,还是要后台返回准确的文件地址
第二种的使用情景就是后台返回的直接是文件流形式。js在浏览器环境中是不能像其他语言一样对文件进行操作的(比如C的fread,java的读取文件操作等等)。
那么由于文件在网络中传输都是以二进制流形式传输的,所以我们要借助一个特殊的对象=>Blob
Blob对象表示一个不可变的, 原始数据的类似文件对象,blob对象本质上是js中的一个对象,里面可以储存大量的二进制编码格式的数据。实际上file类也是从blob类继承来的。
下面演示一下如何用blob对象接收文件流。
this.$axios.get('XXXXXXX',{
responseType:'blob' //告诉服务器我们需要的响应格式
})
.then(res => {
let blob = new Blob([res.data],{
type:'application/vnd.ms-excel' //将会被放入到blob中的数组内容的MIME类型
});
let objectUrl = URL.createObjectURL(blob); //生成一个url
window.location.href = objectUrl; //浏览器打开这个url
})
.catch(err => {
console.log(err);
})
MIME类型 是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开
通过以上代码,我们就可以让文件流被正确下载啦
最后来说说为什么我认为只实现了80%的期望功能。上述构造Blob对象的方式,生成的文件名是由Blob对象随机生成的一段随机数,并不是期望的文件名。我暂时没有找到在使用Blob的同时设置指定的文件名,希望大佬们多多指教