前后端 数据流下载文件

1. 前端取流接口

需要补充 responseType: 'blob'参数,用来限定响应数据类型。

function loadBlob(params) {
  return axios({
    method: 'get',
    url: '/download',
    params,
    responseType:'blob',
  })
}

2. 接口取值

常规取流后,转为 Blob 类文件对象。

async fetchResource(params) {
  try {
    const res = await Api.streamDownload(params)
    const {data, headers} = res || {}
    // 二进制流
    const href = window.URL.createObjectURL(new Blob([data]))
    const fileName = headers['content-disposition']?.split('=')[1] || 'video.mp4';
    // 创建a标签下载
    const dom = document.createElement('a');
    dom.href = href;
    dom.download = fileName;
    dom.style.display = 'none';
    document.body.appendChild(dom);
    dom.click();
    dom.parentNode.removeChild(dom);
    window.URL.revokeObjectURL(href);
  } catch (err) {
    console.log(err)
  }
},

3. 捕获异常

由于请求头中限制了响应类型,假如资源不存在或者取流报错,用这种方式接收到的 response 响应体也是 Blob 类型,无法直接读取,需要从 Blob 中读取内容,对以上方法进行修改

async fetchResource(params) {
  try {
    const res = await Api.streamDownload(params)
    const {data, headers} = res || {}
    const type = headers['content-type'];
    if(type.includes('json')) {
      return this.loadErrResp(data).catch(err=>{
        err?.code == 11 && this.$message.success('下载失败');
      })
    }
    // 二进制流
    const href = window.URL.createObjectURL(new Blob([data]))
    const fileName = headers['content-disposition']?.split('=')[1] || 'video.mp4';
    // 创建a标签下载
    this.downloadResource(href, fileName)
  } catch (errBlock) {
    console.log(errBlock)
  }
},
loadErrResp (data) {
  return new Promise((resolve, reject)=>{
    const reader = new FileReader()
    reader.onload = () => {
      const { result } = reader
      const errorInfos = JSON.parse(result)
      reject(errorInfos)
    }
    reader.onerror = err => {
      reject(err)
    }
    reader.readAsText(data)
  })
},
downloadResource ( href, fileName ) {
  const dom = document.createElement('a');
  dom.href = href;
  dom.download = fileName;
  dom.style.display = 'none';
  document.body.appendChild(dom);
  dom.click();
  dom.parentNode.removeChild(dom);
  window.URL.revokeObjectURL(href);
},

附base64转文件:

function downloadFileByBase64() {
    var fileType = 'pdf';
    var base64Str = 'data:application/pdf;base64,*****'

    // 前缀
    var hasPrefix = base64Str.indexOf('base64,') >= 0;

    if (!hasPrefix && !fileType) {
      alert('请选择文件后缀');
      return false;
    }

    if (!hasPrefix) {
      base64Str = getBase64Type(fileType) + base64Str;
    }

    var myBlob = dataURLtoBlob(base64Str);
    var myUrl = URL.createObjectURL(myBlob);

    downloadFile(myUrl, '');
  }

  // 获取前缀
  function getBase64Type(type) {
    switch (type) {
      case 'txt': return 'data:text/plain;base64,';
      case 'doc': return 'data:application/msword;base64,';
      case 'docx': return 'data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,';
      case 'xls': return 'data:application/vnd.ms-excel;base64,';
      case 'xlsx': return 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,';
      case 'pdf': return 'data:application/pdf;base64,';
      case 'pptx': return 'data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64,';
      case 'ppt': return 'data:application/vnd.ms-powerpoint;base64,';
      case 'png': return 'data:image/png;base64,';
      case 'jpg': return 'data:image/jpeg;base64,';
      case 'gif': return 'data:image/gif;base64,';
      case 'svg': return 'data:image/svg+xml;base64,';
      case 'ico': return 'data:image/x-icon;base64,';
      case 'bmp': return 'data:image/bmp;base64,';
      case 'csv': return 'data:text/csv;base64,';
      default: return 'data:application/octet-stream;base64,'
    }
  }

  function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
  }

  function downloadFile(url, name) {
    var a = document.createElement("a");
    a.setAttribute("href", url);
    // 加上这句话可下载
    a.setAttribute("download", name)
    a.setAttribute("target", "_blank");
    let clickEvent = document.createEvent("MouseEvents");
    clickEvent.initEvent("click", true, true);
    a.dispatchEvent(clickEvent);
  }
posted @ 2022-08-10 14:31  晨の风  阅读(171)  评论(0编辑  收藏  举报