前端解决下载文件(批量下载),被浏览器打开预览的问题

前端解决下载文件,被浏览器打开预览的问题

问题

  • 后端返回的是文件路径,而不是文件流。
  • 需求要下载文件而不是浏览器预览文件。
  • 追加需求可以批量下载文件。

解决思路

一般下载文件都是用的window.open() ,但是如果下载的文件浏览器如果支持预览,会被直接打开而不会下载。我们需要用fetch()转成文件流,然后下载。
写一个公共方法,需要调用的地方引用。

实现

// 调用时候 传入需要下载的文件地址的数组就可以
class download {
  constructor(urls) {
    //所有的url以及文件名
    this.urls = urls
    //全部队列
    this.allQueue = []
    //成功文件
    this.successFiles = []
    //失败文件
    this.errorFiles = []
  }
  //下载文件并转化为blob
  fetchFileAsBlob(url, filename) {
    if (!url) {
      this.errorFiles.push(filename)
      return
    }
    return new Promise((resolve) => {
      fetch(url, {
        mode: 'cors',
      })
        .then((res) => {
          if (res.status == 200) {
            // res返回的是字节流
            res
              .blob()
              .then((blob) => {
                // 使用blob()方法返回一个被解析为Blob格式的Promise对象
                const blobUrl = window.URL.createObjectURL(blob) // 使用URL.createObjectURL 生成一个blob协议的URL,大多数场景下可以将其当做http协议的url来使用
                this.successFiles.push({
                  url: blobUrl,
                  name: decodeURIComponent(filename),
                })
                resolve()
              })
              .catch(() => {
                resolve()
                this.errorFiles.push(filename)
              })
          } else {
            resolve()
            this.errorFiles.push(filename)
          }
        })
        .catch(() => {
          resolve()
          this.errorFiles.push(filename)
        })
    })
  }
  //统一将blob文件下载并返回错误文件
  downloadAllFils(cb) {
    Promise.all(this.allQueue).then(() => {
      cb(this.errorFiles)
      this.successFiles.forEach((item) => {
        const a = document.createElement('a') // 创建一个a标签
        a.style.display = 'none'
        a.href = item.url
        a.download = decodeURIComponent(item.name) // 对编码后的 URI 进行解码
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        window.URL.revokeObjectURL(item.url) // 当不结束使用某个 URL 对象之后,应该通过调用这个方法来让浏览器知道不用在内存中继续保留对这个文件的引用了
      })
    })
  }
  download(cb) {
    this.urls.forEach((item) => {
      this.allQueue.push(this.fetchFileAsBlob(item.url, item.filename))
    })
    this.downloadAllFils((errors) => {
      cb(errors)
    })
  }
}
export { download }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值