更优雅的文件下载方式:前端异步下载文件实现方案


theme: channing-cyan

更优雅的文件下载方式:前端异步下载文件实现方案

需求分析:

下载文件通常是通过打开一个非异步的get请求,但这样我们无法知道浏览器的下载进度以及什么时候下载完成(注意区分,浏览器知道和本应用知道的区别)。比如我们需要在下载过程添加自定义loading,以及下载完成后去做别的事。通过异步获取文件流,然后再下载文件的方式就能很好实现上述需求。

主要思路:

第一步,先通过异步请求(axios或xhr等),获取接口返回的字符流或blob,如果返回的是字符流,前端可自己通过new Blob() 转换成blob;

第二步,通过a标签下载blob;

第三部,下载完成,释放blob,将a标签从文档中移除。

注意:解决 ie 不支持直接下载 blob资源,可通过window.navigator.msSaveOrOpenBlob(blob, filename)实现

方案一:使用 axios 异步获取 blob

```js // 需要注意下载 excel 时, axios 或 xhr 请求需要将 xhr.responseType = "blob" // 否则下载后的 excel 会打不开 // 返回类型blob downloadExcel (params) { // 封装过的 axios this.$api.downloadExcel(params).then(res => { let filename = res.headers['filename'] // const blob = new Blob([res.data]) // 将字符流转换为 blob对象 blobDownload(res.data, decodeURIComponent(filename)) }).finally(() => { this.loading = false }) },

/** * 下载文件:下载 blob 对象形式的文件 * @param blob * @param filename */ export function blobDownload (blob, filename = '文件.txt') { let url = window.URL.createObjectURL(blob) // 解决 ie 不支持直接下载 blob资源 if ('msSaveOrOpenBlob' in navigator) { window.navigator.msSaveOrOpenBlob(blob, filename) return } let link = document.createElement('a') link.style.display = 'none' link.href = url link.download = filename document.body.appendChild(link) link.click() document.body.removeChild(link) // 下载完成移除元素 window.URL.revokeObjectURL(url) // 释放掉blob对象 }

// 创建axios实例 const service = axios.create({ headers: { 'kms-token': localStorage.getItem('token') || '' }, baseURL: config.ip, timeout: 2 * 600000, withCredentials: true // 表示跨域请求时是否需要使用凭证,开启后,后端服务器要设置允许开启 })

// request拦截器 service.interceptors.request.use( config => { const token = localStorage.getItem('token') if (config.url === '/api/excel/upload/knowledge/download') { // 返回类型blob,不设置会打不开 excel config.responseType = 'blob' // config.headers['Content-Type'] = 'application/x-download' } return config }, error => { // console.warn(error) return Promise.reject(error) } ) ```

写法二:使用 xhr 异步获取 blob

js downloadExcel2 (params) { const token = localStorage.getItem('token') || '' const url = 'http://192.168.0.0' + ':8079/' + '/api/excel/download' let xhr = new XMLHttpRequest() // POST方式 xhr.open('POST', url + '?timeStamp=' + new Date().getTime(), true) xhr.setRequestHeader('Cache-Control', 'no-cache') xhr.setRequestHeader('Content-type', 'application/json') xhr.setRequestHeader('token', token) // 返回类型blob,不设置会打不开 excel xhr.responseType = 'blob' // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑 xhr.onload = function () { // 请求完成 if (this.status === 200) { let blob = this.response let reader = new FileReader() // 转换为base64,可以直接放入a表情href reader.readAsDataURL(blob) reader.onload = function (e) { // 转换完成,创建一个a标签用于下载 let a = document.createElement('a') a.download = '收支清单.xlsx' a.href = e.target.result a.click() } } } xhr.send(JSON.stringify(params)) }

常规的同步下载文件方案

js download (url) { const a = document.createElement('a') a.href = url // 下载链接 a.download = 'filename' // 设置 download 属性告诉浏览器执行下载操作,可赋值文件名 a.click() }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值