前端将二进制数据流转为文件_前端下载二进制流文件

本文主要介绍如何在前端将后台返回的二进制数据流转换为文件进行下载,通过设置axios的responseType为arraybuffer,利用Blob对象创建URL并创建隐藏的a标签实现下载。同时讨论了如何根据后台返回内容判断文件是否过大,过大则前端提示错误。
摘要由CSDN通过智能技术生成

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

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

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,

接下来再看看结果是否正确。

axios({

method: 'post',

url: '/export',

responseType: 'arraybuffer',

})

.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)

})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值