前端下载文件

文件下载是在开发中常见的一种需求,下面是在实际项目中使用的下载方案,记录一下

一、打开新页面下载文件

这是最简单的一种下载方案,通过打开新窗口的方法触发浏览器自带的下载功能,可以这样做

const url = "aaaa" // 后端提供的下载接口
// 1、通过window.open打开新窗口
window.open(url); // 打开新窗口,默认的target参数为_blank,在新窗口打开,也可以设置为_self之类的

// 2、也可以通过a标签打开新窗口
const a = document.createElement("a");
a.href = "aaaa";
a.download = "filename"; // 对比与window下载,特点在于可以设置下载下来的文件名
a.click();

这种方案是最简单的,但是弊端也很多:

  • 1、对于部分浏览器可以直接展示的文件类型,比如音乐、视频、图片等,浏览器就不会执行下载操作,而是直接进行展示(由responseContent-Type字段判断类型,image/pngimage/jpeg 等浏览器可以直接识别打开的文件,这样就不会执行下载事件。而像octet-stream的二进制流数据,则是无法直接预览的)
  • 2、当接口访问异常或者参数问题等出现错误时,无法进行错误捕获,而是直接在新窗口显示出接口的报错信息,交互体验差
    综上,这是一种简单,需保证接口调用结果正常,且在特定某些文件类型下可以使用的下载方案

二、通过文件流下载

这种方案主要分为两步,第一获取文件,第二下载文件

1、获取文件

获取文件主要是将请求接口返回的结果设置/转化为Blob(Binary Large Object): 二进制大数据对象或者ArrayBuffer(又称类型化数组)

// 原生ajax
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob"; // 设置返回结果为Blob对象
return new Promise(reslove => {
  xhr.onload = () => {
      if(xhr.status === 200) {
        reslove(xhr.response)  
      }  
  }
})
xhr.send();

// axios
return new Promise((resolve, reject) => {
        axios({
            method:'get',
            url,
            responseType: 'arraybuffer' // 也可以设置为blob
        }).then(data => {
            resolve(data.data)
        }).catch(error => {
            reject(error.toString())
        })
    })

// fetch
return new Promise(reslove => {
    fetch(url, { 
                method: "POST",
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(params)}).then(res => {
      res.blob().then(data => {
        reslove(data);
      })
    })
})

2、下载文件

获取文件以后,就可以开始下载文件

getFile().then(blob => { // file就是上面获取到的filedata
  const a = document.createElement('a');
  const url = window.URL.createObjectURL(blob);
  a.href = url;
  a.download = "fileName" ; // 设置下载下来的文件名
  a.click();
  window.URL.revokeObjectURL(url); // 释放通过调用 URL.createObjectURL() 创建的 URL 对象
})

这样一个文件就可以下载下来了

你可能感兴趣的:(前端下载文件)