前端通过blob对象实现Post下载,处理接口返回二进制文件流

场景:一般下载功能前端使用get请求的方式传参,采用window.open(url)来实现下载。

          对于参数比较多的时候,采用post的传参方式,同时后端的返回是二进制的数据流,这个时候我们需要对后端的返回数据进行blob对象的处理,转化成正常的数据,然后实现下载。

后端的返回结果如下:

此时在页面直接调用下载的方法,下载方法如下:


  previewDocument = query => {
    const lastQuery = { ...query };  // 使用浅拷贝保证多个参数的情况
    lastQuery.currency = 'CNY';
    if (lastQuery.relatedDocumentId) {
      lastQuery.contractWordId = query.relatedDocumentId;
    } else {
      const wordType = [0, 0, 0];
      _.each(lastQuery.wordType, item => {
        if (item === '1') {
          wordType[0] = 1;
        }
        if (item === '2') {
          wordType[1] = 1;
        }
        if (item === '3') {
          wordType[2] = 1;
        }
      });
      lastQuery.contractWordType = _.join(wordType, '');
    }
    delete lastQuery.relatedDocument;
    delete lastQuery.wordType;
    delete lastQuery.relatedDocumentId;
    const action = `${window.location.origin}/galaxy/webapi/galaxy/libraSett/previewGoldLeaseContractDocument`;
    const api = apiCreator();
// 调用api里面封装好的postDownload方法,将参数和方法传到方法里
    api.postDownload(action, lastQuery, '', this.filenameError);
  };

  filenameError = () => { // 对后端返回文件不存在的情况做处理
    message.error('文件名不存在,下载预览失败!');
  };

在api中,postDownload方法如下所示:

postDownload(url, query, defaultFilename, errorHandler) {
      const finalUrl = padPrefix(url);
      const headers = this.getHeaders({
        ...authInfo,
        'Content-Type': 'application/json',
        langCode: this.langCode(),
      });
      return requestPostDownload( // 调用工具类中的requestPostDownload方法
        finalUrl,
        {
          method: 'POST',
          headers,
          body: JSON.stringify(query),
        },
        defaultFilename,
        errorHandler
      );
    },

requestPostDownload方法如下所示:

export default function request(url, options, defaultFilename, errorHandler) {
  let filename = '';

  return Promise.race([
    fetch(url, { credentials: 'include', ...options })
      .then(response => {
        const disposition = response.headers && response.headers.get('content-disposition');
        filename =
          disposition && disposition.indexOf('=') > -1
            ? decodeURI(disposition.substring(disposition.indexOf('=') + 1))
            : defaultFilename;

        if (!defaultFilename && !filename) {
          throw new Error('文件名不存在');
        } else {
          return response.blob();
        }
      })
      .then(blob => {
        const objectUrl = URL.createObjectURL(blob);

        let downloadLink = document.getElementById('downloadLink');
        if (!downloadLink) {
          downloadLink = document.createElement('a');
          downloadLink.setAttribute('id', 'downloadLink');
          downloadLink.setAttribute('style', 'display:none');
          document.body.appendChild(downloadLink);
        }
        downloadLink.setAttribute('download', filename);
        downloadLink.setAttribute('href', objectUrl);
        downloadLink.click();
        URL.revokeObjectURL(objectUrl);
        return blob;
      })
      .catch(error => {
        if (errorHandler) {
          errorHandler(error);
        }
      }),
    new Promise((rosolve, reject) => {
      // eslint-disable-line
      setTimeout(
        // () => reject('请求超时'),
        config.timeout
      );
    }),
  ]);
}

综上所述,即可完成post方式的同时后端返回二进制数据流处理的下载功能。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值