前端文件下载方式(待补充...

1,475 阅读3分钟

常用的几种方式

  • 使用 a 标签直接点击 url
  • 使用 iframe 标签挂载
  • 使用 axios请求url 进行 blob 转换,再添加 a 标签
  • 使用 表单提交

a 标签点击方式

步骤

  1. 获取到接口地址 url

  2.  const link = document.createElement('a')
     link.style.display = 'none'
     link.href = url
     link.setAttribute('download', 'test.zip')
     link.click()
    

    注意:关于 a 标签的 download 属性用法

优缺点

  1. 优点1 方式简单,一般都能实现, 不需要额外写进度条
  2. 优点2 a 标签无需挂载到 dom,只需要给这个a 标签执行 click() 事件就能触发浏览器下载文件
  3. 缺点 遇到连续点击不同的文件下载时,或网络速度慢时,如果服务器尚未反应时就连续下一个文件下载(请求会被cancel 掉),会出现上一个文件未能下载的情况,也就是只有最后一个点击下载生效

iframe 标签挂载方式

步骤

  1. 获取到接口地址 url
  2.  const link = document.createElement('iframe')
     link.style.display = 'none'
     link.src = url
     // 注意 iframe 标签必须挂载到 dom 上,否则无法触发浏览器下载(也是缺点之一)
     document.body.appendChild(link)
    

优缺点

  1. 优点1 方式简单,一般也都能实现,不需要额外写进度条
  2. 优点2 遇到连续下载不同文件,能避免服务器未反应的情况,即请求不会被cancel(解决 a 标签的问题)
  3. 缺点1 iframe 标签必须挂载到 dom 上,并且在请求未成功前不能删除

axios请求url 方式

步骤

  1. 步骤1 需要一个能将请求结果转换成 blob 流格式的 axios 实例,去请求该 url

    (此处假设请求方式为 get 请求)

    注意:代码中几个比较重要的 api ( 摘取自 MDN )

    (1). responseType:

    XMLHttpRequest.responseType属性是一个枚举类型的属性,返回响应数据的类型。它允许我们手动的设置返回数据的类型。如果我们将它设置为一个空字符串,它将使用默认的"text"类型。

    在工作环境 (Work Environment) 中将 responseType 的值设置为 "document" 通常会被忽略. 当将 responseType 设置为一个特定的类型时,你需要确保服务器所返回的类型和你所设置的返回值类型是兼容的。那么如果两者类型不兼容呢?恭喜你,你会发现服务器返回的数据变成了 null ,即使服务器返回了数据。还有一个要注意的是,给一个同步请求设置 responseType 会抛出一个 InvalidAccessError 的异常。

    responseType 支持以下几种值:

    (2). FileReader:

    FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob 对象指定要读取的文件或数据。

    (3). HTTP Header:

    content-type 根据实际请求头判断, 普通数据请求中会返回 'application/json; charset=utf-8'

  2. 步骤2 需要一个文件转换的方法 blobToFile( blob, fileName )

    思路是:根据请求返回的 blob 对象,利用 URL.createObjectURL() 获得该文件二进制流的 URL对象,然后再执行新建 a 标签,执行点击(这里与第一种 a 标签方法类似),最后释放这个 URL对象)

  3. 步骤3 调用请求下载方法,并执行文件转换,即:

    // 引入相关文件
    import { DOWNLOAD_GET } from './API/get'
    import blobToFile from from '@/utils/blobToFile'
    
    // methods
    getDownLoadFile() {
        return DOWNLOAD_GET(`${url}`) 
    }
    async downLoadFile() {
        // this.url 是这个文件的地址
        // this.fileName 是这个文件的文件名,这里稍后补充如何自动填入
        try {
            const blob = await this.getDownFile(this.url)
            blobToFile(blob, this.fileName)
        }
    }