前端文件下载-支持Blob和Json

241 阅读1分钟

背景

下载文件接口,在支持正常文件流下载的同时,需支持失败错误提示。

  1. 正常情况下:返回blob格式数据。
  2. 异常情况下:返回json数据,提示用户失败原因。

问题

接口的responseType只能设置一种格式,responseType="blob"或者responseType="application/json"。这里支持文件下载,需设置为blob,这时返回json时,获取responseText会报错。

responseText: [Exception: DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest'

解法

responseType设置为blob

  1. 返回blob数据时,进行接收下载。
const link = document.createElement('a');
link.style.display = 'none';
// a 标签的 download 属性就是下载下来的文件名
link.download = fileName;
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
// 释放的 URL 对象以及移除 a 标签
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
  1. 返回json数据时,将blob格式转换为json
const reader = new FileReader();
reader.readAsText(blob, 'utf-8');
reader.onload = function(e) {
  const readerRes = reader.result;
  const parseObj = JSON.parse(readerRes);
  const { code, msg } = parseObj;
  // 处理逻辑...
};

总结

const downloadBlob = (url, fileName = '', extraOptions) => {
  const options = {
    credentials: 'include',
    ...extraOptions
  };
  fetch(url, options).then(res => {
    res.blob().then(blob => {
      if (blob.type == 'application/json') {
        const reader = new FileReader();
        reader.readAsText(blob, 'utf-8');
        reader.onload = function(e) {
          const readerres = reader.result;
          const parseObj = JSON.parse(readerres);
          const { code, msg } = parseObj;
          if (code === 'xxx') {
            Modal.error({
              title: '提示',
              content: msg
            });
          } else {
            message.error('导出失败');
          }
        };
        return;
      }

      if (window.navigator.msSaveOrOpenBlob) {
        navigator.msSaveBlob(blob, fileName);
      } else {
        const link = document.createElement('a');
        link.style.display = 'none';
        // a 标签的 download 属性就是下载下来的文件名
        link.download = fileName;
        link.href = URL.createObjectURL(blob);
        document.body.appendChild(link);
        link.click();
        // 释放的 URL 对象以及移除 a 标签
        URL.revokeObjectURL(link.href);
        document.body.removeChild(link);
      }
    });
  });
};