• 前端实现文件下载的方法


    前端实现文件下载

    前端下载一般分为两种情况,一种是后端直接给一个文件地址,通过浏览器打开就可以下载,另外一种则需要发送请求,后端返回二进制流数据,前端解析流数据,生成URL,实现下载。

    一、location.href

    对于一些浏览器无法识别的文件格式,可以直接再浏览器地址栏输入url即可触发浏览器的下载功能。对于单文件下载没有什么问题,但是如果下载多文件,点击过快就会重置掉前面的请求

    适用场景:

    • get请求
    • 单文件下载
    window.location.href = url;
    
    • 1

    二、window.open

    和location.href类似

    window.open(url);
    
    • 1

    三、a标签

    直接下载仅适用于浏览器无法识别的文件。如果是浏览器支持的文件格式,如html、jpg、png、pdf等,则不会触发文件下载,而是直接被浏览器解析并展示,这种情况下,可以使用a标签下载文件,download属性可以设置文件名。适用于单文件下载,如果下载多文件,点击过快就会重置掉前面的请求。

    适用场景:

    • get请求
    • 单文件下载
    • 需要自定义文件名
    //写法1
    const download = (filename, url) => {
        let a = document.createElement('a'); 
        a.style = 'display: none'; // 创建一个隐藏的a标签
        a.download = filename;
        a.href = url;
        document.body.appendChild(a);
        a.click(); // 触发a标签的click事件
        document.body.removeChild(a);
    }
    // 写法2
    <a href="/images/download.jpg" download="myFileName">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:有时候对于浏览器可识别的文件格式,我们还是需要直接下载的情况,可以声明一下文件的header的 Content-Disposition信息,告诉浏览器,该链接为下载附件链接,并且可以声明文件名

    Content-Disposition: attachment; filename="filename.xls"
    
    • 1

    四、文件流

    如果需要使用post请求,且后端返回是一个文件流形式,那么前端需要自己将文件流转成链接,然后下载。 二进制流大概长这样: image.png 适用场景:

    • post请求
    • get请求
    • 多文件

    1.请求的方式

    注意:不可以使用JQuery,因为JQuery不支持blob类型。

    原生js写法

    const req = new XMLHttpRequest();
    req.open('POST', '/download/excel', true);
    req.responseType = 'blob'; //如果不指定,下载后文件会打不开
    req.setRequestHeader('Content-Type', 'application/json');
    req.onload = function() {
        var content = req.getResponseHeader("Content-Disposition") ;
        // 文件名最好用后端返的Content-disposition
        // 需要后端设置 Access-Control-Expose-Headers: Content-disposition 使得浏览器将该字段暴露给前端
        var name = content && content.split(';')[1].split('filename=')[1];
        var fileName = decodeURIComponent(name)
        downloadFile(req.response,fileName)
    };
    req.send( JSON.stringify(params));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    axios写法

    axios({
      method: 'post',
      headers: {
        'Content-Type': 'application/json; charset=utf-8'
      },
      url: '/robot/strategyManagement/analysisExcel',
      responseType: 'blob',
      headers: { //如果需要权限下载的话,加在这里
            Authorization: '123456'
        }
      data: JSON.stringify(params),
    }).then(function(res){
       var content = res.headers['content-disposition'];
       var name = content && content.split(';')[1].split('filename=')[1];
       var fileName = decodeURIComponent(name)
       downloadFile(res.data,fileName)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.文件下载的方式

    通过URL.createObjectURL()下载

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

    downloadFile:function(data,fileName){
        // data为blob格式
        var blob = new Blob([data]);
        var downloadElement = document.createElement('a');
        var href = window.URL.createObjectURL(blob);
        downloadElement.href = href;
        downloadElement.download = fileName;
        document.body.appendChild(downloadElement);
        downloadElement.click();
        document.body.removeChild(downloadElement);
        window.URL.revokeObjectURL(href);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    通过# FileReader.readAsDataURL()下载

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

    downloadFile:function(data,fileName){
       const reader = new FileReader()
       // 传入被读取的blob对象
       reader.readAsDataURL(data)
       // 读取完成的回调事件
       reader.onload = (e) => {
           let a = document.createElement('a')
           a.download = fileName
           a.style.display = 'none'
           // 生成的base64编码
           let url = reader.result
           a.href = url
           document.body.appendChild(a)
           a.click()
           document.body.removeChild(a)
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    两者的区别

    • 返回值

    FileReader.readAsDataURL(blob)可以得到一段base64的字符串
    URL.createObjectURL(blob)得到的是当前文件的一个内存url

    • 内存

    FileReader.readAsDataURL(blob)依照js垃圾回收机制自动从内存中清理 URL.createObjectURL(blob)存在于当前document内,清除方式通过revokeObjectURL()手动清除

    • 执行方式

    FileReader.readAsDataURL(blob)通过回调的方式f返回,异步执行
    URL.createObjectURL(blob) 直接返回,同步执行

    • 多个文件

    FileReader.readAsDataURL(blob)同时处理多个文件时,需要一个文件对应一个FileReader对象
    URL.createObjectURL(blob) 依次返回,没有影响

    • 优势对比

    URL.createObjectURL(blob)得到本地内存容器的URL地址,方便预览,需要注意手动释放内存的问题,性能优秀。
    FileReader.readAsDataURL(blob)可直接转为base64格式,直接用于业务

    五、插件downloadjs

    下载

     npm install --save downloadjs
    
    • 1

    引入插件

    import download from "downloadjs"
    // or
    const download = require('downloadjs')
    
    • 1
    • 2
    • 3

    使用

      export const downloadFile = (res, type, filename) => {
        // 将二进制流转成blob对象
        const blob = new Blob([res], {
          type: type
        })
        // 调用插件方法
        download(blob, filename, type);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    微信“史诗级”更新,小而美终于回来啦~
    【面试精讲】深克隆和浅克隆的实现方式?深克隆和浅克隆有什么区别?
    软件测试面试题 —— 整理与解析(4)
    使用ExLlamaV2量化并运行EXL2模型
    C语言,洛谷题,赦免战俘
    Vue3 企业级优雅实战 - 组件库框架 - 3 搭建组件库开发环境
    Golang协程WaitGroup
    JVM运行时数据区——虚拟机栈
    【java:牛客每日三十题总结-6】
    C专家编程 第11章 你懂得C,所以C++不再话下 11.2 抽象---取事物的本质特性
  • 原文地址:https://blog.csdn.net/MoXinXueWEB/article/details/126092614