问题

我们在后台管理系统开发的过程中,时常会遇到下载文件的需求。当我第一次遇到这个问题的时候,我的的心里活动是“这多简单,动态创建a标签,直接模拟点击后下载”。一开始是没有问题的,做着做着就有一些疑问:

  • 如何知道下载文件进度?
  • 如何知道下载是否成功?

这些都是直接动态创建a标签无法解决的

解决方案

在研究过网上不少方案下,总结了一套适合自己的方法:

通过 fetch 去请求后端给的url(当然也可以是axios),然后返回数据通过 blob() 去创建Blob对象,再走常规的动态创建a标签流程即可实现下载功能。

  1. const ele = document.createElement('a')
  2. fetch(url).then(r => {
  3. r.blob().then(blob => {
  4. const href = URL.createObjectURL(blob)
  5. ele.href = href
  6. ele.download = ''
  7. ele.click()
  8. URL.revokeObjectURL(href)
  9. })
  10. })

如何控制下载状态

可以使用Promise实现

  1. function download () {
  2. return new Promise((resolve, reject) => {
  3. fetch(url).then(r = {
  4. resolve()
  5. })
  6. })
  7. }
  8. download().then(() => {
  9. console.log('success !')
  10. })

如此一来,就可以在外部控制下载的状态,加强了用户体验。