前端文件下载,后端返回文件流方式,兼容ie浏览器

本文介绍了一种兼容IE浏览器的文件下载方法,利用后端返回的文件流并通过前端JavaScript处理,实现了不同浏览器环境下一致的文件下载体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、考虑兼容性ie浏览器

代码示例如下:

// 文件下载,后端返回文件流方式,兼容ie浏览器
const fileDownload = (fileName, params) => {
  showLoading();//出现load动画
  Api.get(xxxfiledownloadurl, {
    params,
    responseType: 'blob',
    headers: {
      isShowLoading: false, // 不要全局loading,使用自定义的loading,需要在封装的Api拦截方法中设置一下,略...
    }
  })
    .then(res => {
      const data = res.data;
      let content;
      let reader = new FileReader();
      reader.onload = event => {
        content = reader.result;
        try {
          const obj = JSON.parse(content);
          if (obj && obj.code && obj.message) { // 因为blob返回的错误catch接收不了,只能使用FileReader读取再做出提示
            return alert(`${obj.code}-${obj.message}`);
          }
          else if (window.navigator && window.navigator.msSaveBlob) {
            // 兼容ie浏览器
            return window.navigator.msSaveBlob(data, fileName);
          }
          else {
            reader.readAsDataURL(data);
          }
        }
        catch (err) {
          return saveAs(data, fileName)
        }
      }
      reader.saveAsText(data)
    }).catch(err => {
      // 正常的接收到的错误提示--根据打印的内容筛选出需要进行错误的提示内容,略...
      console.log(Object.values(err));
    })
    .finally(() => {
      hideLoading();//隐藏load动画
    })
}

// 注意: 如果是post请求:
Api.post(xxxfiledownloadurl, params对象, {
    responseType: 'blob',
    headers: {
      isShowLoading: false, // 不要全局loading,使用自定义的loading,需要在封装的Api拦截方法中设置一下,略...
    }
})
.then(res=>{略...}).catch(err=>{略...});

二、如果不考虑兼容性问题

1.await+TextDecoder+arrayBuffer

也可以使用下面downloadExcel方法:

思路:

  • 一般情况下如果成功下载,data直接返回文件流数据,它无法使用parse解析;
  • 如果下载报错,返回的json字符串就可以使用parse解析成对象;
  • 巧用trycatch,try中获取报错信息,catch中下载文件。
import _ from 'lodash';
import axios from 'axios';

async function blobToJson(blob) {
  const decoder = new TextDecoder('utf-8'); // 创建一个TextDecoder实例来解码UTF-8编码的文本
  const text = decoder.decode(await blob.arrayBuffer()); // 将Blob转换为ArrayBuffer,然后解码为文本
  return JSON.parse(text); // 解析文本为JSON对象
}
async function downloadExcel(params) {
  const res = await axios({
      url: '/download/file/xxx',
      method: 'get',
      responseType: 'blob',
      params,
    });
  const data:any = _.get(res,'data');
  const fn = () => {
    const url = window.URL.createObjectURL(data);
    const elink = document.createElement('a');
    elink.href = url;
    elink.target = '_self';
    elink.setAttribute('download', 'xxx.xlsx');
    elink.style.display = 'none';
    document.body.appendChild(elink);
    elink.click();
    document.body.removeChild(elink);
  }
  try {
    const result = await blobToJson(data);
    if (result && result.message) {
      const $message = window['$message'];
      $message.error(result?.msg || result?.message);
    }
  }
  catch (err) {
    fn();
  }
  return res;
}

2.普通Promise+fileReader

思路:

  • 如果后端有控制responseHeader的content-disposition,成功返回文件流就有在responseHeader中添加content-disposition;
  • 下载接口报错就没有在responseHeader中添加content-disposition;
  • 如果responseHeader中没有content-disposition,就利用FileReader获取错误信息,否则就直接下载文件。
function downloadExcel(params) {
  return axios({
      url: prefix + '/download/file/xxx',
      method: 'post',
      responseType: 'blob',
      data: params,
    })
    .then((res) => {
      if (!res.headers['content-disposition']) {
        const fileReader = new FileReader();
        fileReader.readAsText(
          new Blob([res.data || ''], { type: 'application/octet-stream' }),
          'utf-8'
        );
        fileReader.onload = () => {
          const result = JSON.parse(fileReader.result || '{}');
          const $message = window['$message'];
          $message.error(result?.msg || result?.message);
        };
        return;
      }
      const url = window.URL.createObjectURL(res.data);
      const elink = document.createElement('a');
      elink.href = url;
      elink.target = '_self';
      elink.setAttribute('download', 'xxx.xlsx');
      elink.style.display = 'none';
      document.body.appendChild(elink);
      elink.click();
      document.body.removeChild(elink);
    });
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值