Skip to content

前端文件下载方案

1. 后端返回文件url路径的场景

该方式将下载逻辑放在后端处理,后端直接返回文件url地址

js
window.location.herf = 'xxxxx' // xxxxx为后端返回的文件路径

2. 后端返回二进制流的场景

根据二进制流数据生成下载URL可以有多种方式实现,具体实现如下:

方案1. 将二进制数据封装为BLOB对象

前端通过创建a标签,为href属性赋值,模拟自动点击事件,最后在清除a标签即可,使用到URL.createObjectURL(object)这个方法.

接收后端传过来的二进制流。默认情况下axios不会处理二进制数据,即请求可以正常被浏览器接收,但是axios不会去处理。需要在请求的时候设置responseType: 'blob'才可以

js
// get 请求
axios({
    method: 'get',
    url,   // 这里自行设置传参
    params, // 这里自行设置传参
    responseType:'blob' // 这里是重点,敲黑板
}).then(res => {
        // 获取响应头中的文件名
        let filename = response.headers  //下载后文件名
        filename = filename["content-disposition"]
        filename = filename.split(";")[1].split("filename=")[1]
        // 创建 a 标签
        let elink = document.createElement('a');
        document.body.appendChild(elink);
        elink.style.display = 'none'; // 隐藏起来
        elink.download = filename
        // 如果后端没有返回,可以自己设置下载文件的名称 elink.download = 'XXX文件.pdf'; 
        let blob = new Blob([res.data]);
        // 兼容webkix浏览器,处理webkit浏览器中herf自动添加blob前缀,默认在浏览器打开而不是下载
        const URL = window.URL || window.webkitURL
        elink.href = URL.createObjectURL(blob) // 通过createObjectURL方法转换成对象url
          
        elink.click();
        document.body.removeChild(elink);
        URL.revokeObjectURL(elink.href); // 释放URL 对象
        
})

方案2. 将二进制数据封装为文件读取FileReader对象

注意: 使用 FileReader对象封装二进制流之后没办法设置下载的文件名,默认文件名为下载,文件格式根据读取的是请求返回的content-type。

js
// utils.js
export const download = (res) => {
  // 创建文件对象
  let reader = new FileReader()
  // 监听读取完毕
  reader.onloadend = function () {
    // 返回base64位的文件内容
    let url = reader.result
    // 下载
    window.location.href = url
  }
  // 开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。
  reader.readAsDataURL(res)
}

方案3. 使用插件downloadjs

(1) 下载插件

bash
 npm install --save downloadjs

插件地址:https://www.npmjs.com/package/downloadjs

(2)引入插件

js
import download from "downloadjs"
// 或者
const download = require('downloadjs')

(3) 使用

js
  export const downloadFile = (res, type, filename) => {
    // 将二进制流转成blob对象
    const blob = new Blob([res], {
      type: type
    })
    // 调用插件方法
    download(blob, filename, type);
  }