JS二进制流文件下载导出(接口返回二进制流)乱码处理方法

 更新时间:2023年12月20日 11:20:37   作者:hzxOnlineOk  
这篇文章主要介绍了JS二进制流文件下载导出(接口返回二进制流)乱码处理方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

给下载文件起名字有两种方式:

  • 固定值+时间戳(一般都加上时间戳)
  • 后端将文件名放到response的headers中返回,我们取值当做文件名

 使用react的同学注意了,fetch难设置乱码转码,建议使用axios,用fetch亲自尝试失败+10086次,下载下来的xlsx全是乱码

平时在前端下载文件有两种方式,一种是后台提供一个 下载的http URL,然后用 window.open(URL)或者创建一个a标签的href属性下载,另一种就是后台直接返回文件的二进制内容,然后前端转化一下再下载。

由于第一种方式比较简单,在此不做探讨。本文主要讲解一下第二种方式怎么实现。

Blob、ajax(axios)
mdn 上是这样介绍 Blob 的:

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据

具体使用方法

axios({
  method: 'post',
  url: '/export',
})
.then(res => {
  // 假设 data 是返回来的二进制数据
  const data = res.data
  const url = window.URL.createObjectURL(new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.setAttribute('download', 'excel.xlsx')
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
})

打开下载的文件,看看结果是否正确。

一堆乱码…

一定有哪里不对。

最后发现是参数 responseType 的问题,responseType 它表示服务器响应的数据类型,由于后台返回来的是二进制数据,所以我们要把它设为 arraybuffer(如果后端传递过来约定的是blob,那么responseType应该设置成这个responseType: 'blob')
接下来再看看结果是否正确。

axios({
  method: 'post',
  url: '/export',
  responseType: 'arraybuffer',
  // responseType: 'blob'
})
.then(res => {
  // 假设 data 是返回来的二进制数据
  const data = res.data
  const url = window.URL.createObjectURL(new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.setAttribute('download', 'excel.xlsx')
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
})

这次没有问题,文件能正常打开,内容也是正常的,不再是乱码。

根据后台接口内容决定是否下载文件
作者的项目有大量的页面都有下载文件的需求,而且这个需求还有点变态。

具体需求如下

如果下载文件的数据量条数符合要求,正常下载(每个页面限制下载数据量是不一样的,所以不能在前端写死)。
如果文件过大,后台返回 { code: 199999, msg: '文件过大,请重新设置查询项', data: null },然后前端再进行报错提示。
先来分析一下,首先根据上文,我们都知道下载文件的接口响应数据类型为 arraybuffer。返回的数据无论是二进制文件,还是 JSON 字符串,前端接收到的其实都是 arraybuffer。所以我们要对 arraybuffer 的内容作个判断,在接收到数据时将它转换为字符串,判断是否有 code: 199999。如果有,则报错提示,如果没有,则是正常文件,下载即可。具体实现如下:

axios.interceptors.response.use(response => {
    const res = response.data
    // 判断响应数据类型是否 ArrayBuffer,true 则是下载文件接口,false 则是正常接口
    if (res instanceof ArrayBuffer) {
        const utf8decoder = new TextDecoder()
        const u8arr = new Uint8Array(res)
        // 将二进制数据转为字符串
        const temp = utf8decoder.decode(u8arr)
        if (temp.includes('{code:199999')) {
            Message({
                // 字符串转为 JSON 对象
                message: JSON.parse(temp).msg,
                type: 'error',
                duration: 5000,
            })
            return Promise.reject()
        }
    }
    // 正常类型接口,省略代码...
    return res
}, (error) => {
    // 省略代码...
    return Promise.reject(error)
})

react fetch(react方案)

const qryurl = `/offapi/liveaum/exportExcelData`;
    fetch(qryurl, {
      method: 'POST',
      credentials: 'include',
      headers: { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' },
      body: JSON.stringify(params),
    }).then(response => {
      if (response.ok) {
        let downloadFileName = decodeURIComponent(response.headers.get('filename'));
        this.setState({ downloadFileName, downModalShow: true, iconLoading: false });
        response.blob().then(blob => {
          downBlob = blob;
        });
      }
    }).catch(function(err) {
      console.log(err);
      downBlob = null;
      message.warning('暂未查询到数据');
      this.setState({ iconLoading: false })
    });
// 导出文件
  handleOk = () => {
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = URL.createObjectURL(downBlob);
    link.download = `${this.state.downloadFileName}.xls`;
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(link.href);
    document.body.removeChild(link);
    message.success('下载成功');
    this.onModalclose();
  };

到此这篇关于JS二进制流文件下载导出(接口返回二进制流)乱码处理的文章就介绍到这了,更多相关js二进制文件下载导出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中的this引用(推荐)

    JavaScript中的this引用(推荐)

    this是javascript的一个关键字,随着函数使用场合不同,this的值会发生变化。这篇文章主要介绍了JavaScript中的this引用的相关资料,非常不错,需要的朋友可以参考下
    2016-08-08
  • JavaScript中FontFace对象的使用方式

    JavaScript中FontFace对象的使用方式

    这篇文章主要介绍了JavaScript中FontFace对象的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 微信小程序中获取用户手机号授权登录详细步骤

    微信小程序中获取用户手机号授权登录详细步骤

    这篇文章主要给大家介绍了关于微信小程序中获取用户手机号授权登录的详细步骤,在微信小程序中开发者可以通过微信提供的API接口实现用户登录和获取用户的手机号,需要的朋友可以参考下
    2023-07-07
  • 基于node.js的快速开发透明代理

    基于node.js的快速开发透明代理

    服务器端js(Server-Side Javascrpt)很早也就有了,JAVA中也有javascript 的script引擎。
    2010-12-12
  • JS实现点击Radio动态更新table数据

    JS实现点击Radio动态更新table数据

    这篇文章主要介绍了JS实现点击Radio动态更新table数据的相关资料,需要的朋友可以参考下
    2017-07-07
  • QQ强制聊天功能代码(加强版,兼容QQ2010)

    QQ强制聊天功能代码(加强版,兼容QQ2010)

    QQ强制聊天功能代码,脚本之家以前也发布过,但已经不能用了,这个是新版本,经过测试,完全兼容新版本的qq.
    2010-06-06
  • js scrollTop如何到达指定位置

    js scrollTop如何到达指定位置

    很早之前就想分享这篇心得,幸之今天能在这里完成,好了,话不多说,进入正题。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • 纯HTML5制作围住神经猫游戏-附源码下载

    纯HTML5制作围住神经猫游戏-附源码下载

    围住神经猫游戏是一款基于html5、jquery、typescript等技术开发的游戏,非常好玩,感兴趣的朋友快来围观吧,体验一把,下面给大家分享使用html5如何制作围住神经猫游戏-附源码下载,有需要的朋友可以参考下
    2015-08-08
  • 微信小程序常用赋值方法小结

    微信小程序常用赋值方法小结

    这篇文章主要介绍了微信小程序常用赋值方法,结合实例形式总结了微信小程序局部变量、全局变量及data对象属性赋值相关操作技巧,需要的朋友可以参考下
    2019-04-04
  • JS遍历数组及打印数组实例分析

    JS遍历数组及打印数组实例分析

    这篇文章主要介绍了JS遍历数组及打印数组的方法,结合实例形式分析JavaScript数组的遍历与打印输出相关技巧,需要的朋友可以参考下
    2016-01-01

最新评论