前端处理各种格式下载文件(excel, zip下载等)

96 阅读2分钟

前言:在前端的开发过程中,经常会遇到各种各样的下载文件处理。其中因为不同原因(不同后端的开发习惯, 信息安全原因)等,下载文件的处理也是各有不同。其中包含常见的excel下载, 压缩文件zip下载等,其实处理方法都是基本相同,对于各种形式的文件应该都是可以下载的。

 

这边对于文件的下载方式进行总结,总的来说只有两种~

1. 后端返回一个url, 前端根据url进行下载

方法1: 创建iframe进行下载

export const downloadFile = url => {
  const divFrame = window.parent.document.getElementById('downLoadListFrame')
  // 判断是否存在,如果存在先移除,再重新创建
  if (divFrame != null) {
    window.parent.document.body.removeChild(divFrame)
  }
  // 重新创建
  const iframe = window.parent.document.createElement('iframe')
  iframe.setAttribute('id', 'downLoadListFrame')
  // download_file.id = "downFrame";
  window.parent.document.body.appendChild(iframe)
  iframe.setAttribute('src', url)
  iframe.style.display = 'none'

  const timer = setTimeout(() => {
    iframe.setAttribute('src', '')
    clearInterval(timer)
  }, 30000)
}

方法2: window.open() 进行下载

window.open(url)

 特点: 这种方式前端更改不了文件名,请让后端设置好。

 

2.后端返回文件的blob流,前端解析后下载

方式1:直接对blob解析

const toLocalFile = (data: any, contentType: any, fileName: string) => {
  const blob = new Blob([data], { type: contentType });
  const url = window.URL.createObjectURL(blob);
  // 打开新窗口方式进行下载
  // window.open(url);

  // 以动态创建a标签进行下载
  const a = document.createElement('a');
  a.href = url;
  a.download = fileName; // 文件名
  a.click();
  window.URL.revokeObjectURL(url);
};

方式2:直接在请求后进行处理下载

export const download = ({ url, params = '', method = 'post' }) => {
  axios({
    method,
    headers: {'Content-Type': 'application/json;charset=utf-8;'
    },
    url: url,
    data: JSON.stringify(params),
    responseType: 'blob'
  })
    .then(res => {
      console.log('res', res, res.data, new Blob([res.data]))
      const filename = res.headers['content-disposition']
        ? res.headers['content-disposition'].split('=')[1]
        : `YHQ${moment().format('YYYYMMDDHHmmss')}.xls`
      const content = res.data
      const blob = new Blob([content])

      if (content.type === 'multipart/form-data') {
        if ('download' in document.createElement('a')) {
          // 非IE下载
          const elink = document.createElement('a')
          elink.download = filename
          elink.style.display = 'none'
          elink.href = URL.createObjectURL(blob)
          document.body.appendChild(elink)
          elink.click()
          URL.revokeObjectURL(elink.href) // 释放URL 对象
          document.body.removeChild(elink)
        } else {
          // IE10+下载
          navigator.msSaveBlob(blob, filename)
        }
      }
    })
    .catch(err => {
      MESSAGE.error(err)
    })
}

特点: 前端可以通过download属性设置文件名

ps:通过请求获取文件名,通常会有个小问题,就是后端是把文件名放在res.headers['content-disposition']中,但是常常前端这边却没有显示。

原因为:默认情况下,只有七种 simple response headers(简单响应首部)可以暴露给外部:

解决方法: 如果想要让客户端可以访问到其他的首部信息,可以将它们在 Access-Control-Expose-Headers 里面列出来。(请让后端进行设置)

// 后端设置
  response.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
  response.setHeader("Content-Disposition", ...)

 

 另外:如果文件安全性要求较高建议使用Blob方式,避免信息泄露以及恶意攻击下载