一些管理系统常常会有导出文件的功能,这里介绍三种文件下载的尝试

1. 通过文件地址下载文件

 此方式最为简易,只需要知道文件在服务器上的地址,就可以通过a标签实现下载

<a href="https://.../158ac1e6917445a4aa384a2a7209445a.xlsx" download="test">下载文件</a>
<a href="https://.../6d0e6934246c4ba9ba1a43c6992836ca.png" download="test">下载图片</a>

已知文件的地址,可以通过上面的方式将地址放入href属性内,download属性存放下载文件的名称,此属性为必须。

若文件地址为异步获取,即点击下载/导出按钮时才会从接口拿,则可以通过js插入a标签来实现。demo如下:

异步获取文件路径之后执行以下代码即可自动下载

// 创建a标签
let a = document.createElement('a')
// 定义下载名称
a.download = '文件名称'
// 隐藏标签
a.style.display = 'none'
// 设置文件路径
a.href = 'https://.../158ac1e6917445a4aa384a2a7209445a.xlsx'
// 将创建的标签插入dom
document.body.appendChild(a)
// 点击标签,执行下载
a.click()
// 将标签从dom移除
document.body.removeChild(a)

缺点:此方式只适用于非图片和非pdf格式的文件下载,当文件为图片或pdf时,浏览器会打开预览,而非下载。

2. 已知文件内容,通过URL.createObjectURL()下载文件

此方式需与后端配合,当点击下载按钮时,请求接口,返回文件流。

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

createObjectURL()支持传入 File 对象、Blob 对象或者 MediaSource 对象(媒体资源)。

Demo:

handleDownload(file) {
  service.get(`/download?fileId${file.id}`,{responseType: 'blob'}).then((blobContent)=>{
      let a = document.createElement('a')
      a.download = file.fileName
      a.style.display = 'none'
      let url = URL.createObjectURL(blobContent)
      a.href = url
      document.body.appendChild(a)
      a.click()
      URL.revokeObjectURL(url) // 销毁
      document.body.removeChild(a)
  }
},

注意URL.createObjectURL()创建的对象使用完成后,即下载后可以通过URL.revokeObjectURL()移除该对象,释放内存。理论上讲dom销毁时,URL.createObjectURL()创建的对象也会随之销毁,我们可以不必手动销毁。但当页面有类似表格形式的文件列表时,下载完文件立即手动销毁对象无疑是最好的选择。

3. 已知文件内容,通过FileReader.readAsDataURL()下载文件

此方式与上一种方式大抵相似,需与后端配合,当点击下载按钮时,请求接口,返回文件流。

readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作为异步操作,当读取完成时,可以从onload回调函数中通过实例对象的result属性获取data:URL格式的字符串(base64编码),此字符串即为读取文件的内容,可以放入a标签的href属性中。

Demo:

handleDownload(file) {
  service.get(`/download?fileId${file.id}`,{responseType: 'blob'}).then((blobContent)=>{
      // 创建FileReader实例
      const reader = new FileReader()
      // 传入被读取的blob对象
      reader.readAsDataURL(blobContent)
      // 读取完成的回调事件
      reader.onload = (e) => {
        let a = document.createElement('a')
        a.download = file.fileName
        a.style.display = 'none'
        // 生成的base64编码
        let url = reader.result
        a.href = url
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
      }
  }
},

总结:第二种方式与第三种方式非常相似,都是通过将blob转成地址,再放入a标签实现下载。

这里推荐一篇博客介绍URL.createObjectURL()FileReader.readAsDataURL()的区别:戳我

 

Logo

快速构建 Web 应用程序

更多推荐