做web前端好久了, 每次碰到上传下载都要去翻之前拿来即用的代码, 今天比较闲, 想来可以记录一下
先说上传下载的业务逻辑
A.提供模版让用户下载,用户填完后,点击按钮选择文件上传。
这种逻辑下,我们可以直接得到文件的地址,可以直接使用下面两种方法进行下载,他们的区别是:地址是否是静态可以直接拿到的。如果是静态地址,可以直接写在模板里面,如果是动态地址,比如请求后端给的,只能通过js形式操作
方法a1. 使用<a>标签直接下载,这样,点击标签就可以触发下载操作了
<el-button>
<a href="文件的本地地址、网络地址" download="下载后文件的名称" />
<el-button/>
方法a2.在JS中进行操作
let link = document.createElement('a');
link.style.display = 'none';
link.href = ‘文件的本地地址、网络地址’;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
B.依旧是下载任务,只不过请求后端后,返回的是二进制数据。
js无法直接处理二进制数据,但是可以借助BLOB对象进行处理(Binary Large Object),这里先不说blob对象,我们直接说怎么用,下期我们重点说这个blob。
首先请求接口如果返回二进制数据,一个很重要的标记就是,请求的config中 responseType = 'blob'
axios中配置
// window.URL.createObjectURL根据传入的参数创建一个指向该参数对象的URL
let url = window.URL.createObjectURL(new Blob([response.data], { type: response.headers['content-type']}));
let link = document.createElement('a');
link.style.display = 'none';
link.href = url;
// 从消息头获取文件名
let str = response.headers['content-disposition'].split(';')[1];
link.setAttribute('download', decodeURIComponent(filename));
// 触发点击下载
document.body.appendChild(link);
link.click();
// 下载完成移除元素
document.body.removeChild(link);
// 释放释放掉blob对象
window.URL.revokeObjectURL(url);
B任务下,我们在请求的时候加上了responseType=‘blob’,表示返回的数据是二进制,正常情况我们可以通过创建blob对象,创建URL,如果发生错误了呢?
我们还需要一个类,FileReader。他可以读取blob流。
const fileReader = new FileReader();
//默认utf-8编码
fileReader.readAsText(res.data, 'encoding');
//读取完毕后(成功的情况)执行的回调函数
fileReader.onload = () => {
const msg = fileReader.result;
const jsonMsg = JSON.parse(msg);
//这里我们得到了错误的msg,就可以提示用户了。
};
//其他情况也可以根据需求使用
onloadstart:读取文件开始时触发
onprogress:读取过程中触发,会返还本次读取文件的最大字节数和已经读取完毕的字节数,可以用来做进度条
onabort:在读取中断时触发
onerror:在读取文件失败时触发
onload:在读取完成时触发
onloadend:读取结束后触发,不论成功还是失败都会触发,触发时机在onload之后
C.上传的话,就不需要多说了,一般都使用<el-upload>即可完成大部分需要
总结:
可以看出来,不管下载什么都离不开a标签,只是不同的只是a标签的链接,第一种业务使用的本地地址或者网络地址,第二种使用的则是通过blob对象创建的URL
网友评论