业务需求
要实现一个文件下载功能,这个下载的文件是后台根据数据处理之后返回的数据流,并且如果文件无法下载,或者是打包文件时出现异常,数据流里面直接返回异常,前段需要输出异常提示。
解决思路
为了实现这样的需求,想到了用 Blob
去接收数据,然后使用 FileReader
去读取无法下载的文件的异常返回,能够下载的文件则走下载的流程(如果是IE10以上的浏览器,则运行 navigator.msSaveBlob(blob, filename)
;如果是其他chrome内核的浏览器,则通过创建a标签的形式来进行下载)
Internet Explorer 10 的 msSaveBlob 和 msSaveOrOpenBlob 方法允许用户在客户端上保存文件,方法如同从 Internet 下载文件,这是此类文件保存到“下载”文件夹的原因。关于msSaveBlob与msSaveOrOpenBlob
代码
export async function apiOutputSelfMarkTable(agr = {}) {
// 获取token
let token = window.localStorage.getItem('token')
// 定义接口api
let url = '/proxy/fydj/perfCheck/exportSelfMarkTable'
// 发送请求
axios({
method: 'post', // post方法
url,
data: agr,
responseType: 'blob',
headers: {
Authorization: token,
},
})
.then(async res => {
const blob = new Blob([res.data])
// 判断是否为数据流文件,如果不是则输出错误原因,
// 如果是则下载该文件
if (res.data.type !== 'application/octet-stream') {
let reader = new FileReader()
reader.readAsText(blob)
// 因为render.readAsText()是异步的,
// 所以下面必修调用onload来加载之前输出的结果
reader.onload = function () {
//读取完毕后输出结果
message.error(this.result)
}
return
} else {
// 定义正则
let negx = new RegExp('attachment;filename=', 'g')
let Str = res.headers['content-disposition']
// 获取文件名称
let filename = decodeURI(Str.replace(negx, ''))
if ('download' in document.createElement('a')) {
// 非IE下载
const elink = document.createElement('a')
elink.download = filename
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
console.log('下载第二步')
} else {
// IE10+下载
navigator.msSaveBlob(blob, filename)
}
}
})
.catch(err => {
console.log(err)
})
}
readAsText
方法可以将 Blob 或者 File [](https://developer.mozilla.org... 对象转根据特殊的编码格式转化为内容(字符串形式)这个方法是异步的,也就是说,只有当执行完成后才能够查看到结果,如果直接查看是无结果的,并返回undefined
也就是说必须要挂载 实例下的 onload 或 onloadend 的方法处理转化后的结果 (引自MDN文档)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。