导出文件请求返回JSON数据和文件流数据处理办法(返回二进制乱码可处理)

背景:在新窝点学习,需求是导出表格(固定,其它文件类型这里不涉及),但后端最大导出量是20W,超过20W查询就返回JSON格式数据,如{“code”: “xxx”, “msg”:“超过20W,导出失败”, xxxx},所以需要前端去做导出数据的处理,废话也不多说,走流程:

一、我们需要处理封装的请求:

ps:我这里使用flyio,也验证过了axios

// 给请求加responseType属性,具体可以查看mdn,
// 看字面意思你可理解为加了此属性可使得响应返回的类型是XXX,
// 因为文件类型,所以需要加blob或者arrayBuffer处理二进制数据
// 可查看文档确认responseType是和url,body等同级,封装下,加上即可
let req = {
	// ...
	url: url, // 忽略
	body: body, // 忽略
	responseType: 'blob' || '' //只关注这里:blob或者arrayBuffer
	// ...
}
// 导出封装,只需要调用方法加接口地址
export function getExport(url) {
  return httpRquest({ url, method: 'GET', responseType: 'arraybuffer' })
}
ps:可了解下Blob和 ArrayBuffer,参考MDN:

Blob
https://developer.mozilla.org/zh-CN/docs/Web/API/Blob

ArrayBuffer
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer

二、返回数据处理:

ps:这里$api内是已经添加接口地址的类,直接调用即可,个人自定义就好,这里只是范例:

  1. responseType为blob

blob数据返回实例图
相关代码:

this.$api.xxx().then((res) => {
     console.log(res); // Blob对象 { size: 1234, type: "xxxxxx"}
     // Blob对象根据mdn描述,如果能解析,type是有值的,不然为空字符串
     // 这里返回是表格文件和JSON数据
     // 因此type会为:
     // 文件:application/octet-stream
     // JSON数据:application/json
     // 进行简单判断为blob对象:
     if(res && res.type) {
     	let type = res.type;
     	if(type === "application/octet-stream") {
			// Blob 对象处理
			let blob = new Blob([res], { type: "application/octet-stream" });
			// 下方代码有处理导出的文件的代码
			return;
		}
		if(type === "application/json") {
			// json 数据处理
			let reader = new FileReader();
			reader.onload = (data) => {
	            // data是个对象 {..., target: { ..., result: 'asda', ....}}
	            // 会有一个target属性里包含了返回的JSON
	            if (data.target && data.target.result) {
	              let result = data.target.result;
	              // 进行自定义校验
	              if (
	                typeof result === "string" &&
	                result.includes("code") &&
	                result.includes("msg")
	              ) {
	                result = JSON.parse(data.target.result);
	                // 自定义处理
	                return;
	              }
	          	}
	        };
	        reader.error= (err)=> {
	        	// 读取失败,自定义处理
	        	console.log(err)
	        }
			// 数据解析为json,理解为读取文件数据
			reader.readAsText(new Blob([res], { type: "application/json" }));
			return;
		}
     }
     // 没有这里直接就算失败吧,根据实际情况自定义
     console.log('导出失败')
}.catch((err) => {
    console.log('导出失败')
});
     

导出下载文件相关代码:

// 此处是拿生成blob类型数据进行表格下载,这个网上一大片,因为项目不兼容低版本ie,所以对此需要更优化的自行百度或者google更好的哦!
let aLink = document.createElement("a");
aLink.addEventListener("click", (e) => {
    aLink.download = `表格名称.xls`;
    aLink.href = URL.createObjectURL(blob);
});
let e = document.createEvent("MouseEvents");
e.initEvent("click", false, false);
aLink.dispatchEvent(e);
  1. responseType为arrayBuffer
this.$api.xxx().then((res) => {
     console.log(res); // arrayBuffer数据
     // Blob对象根据mdn描述,如果能解析,type是有值的,不然为空字符串
     // 这里返回是表格文件和JSON数据
     // 文件:application/octet-stream 
     // JSON数据:application/json
     var reader = new FileReader();
     reader.onload = (data) => {
	     // 是错误信息返回
	     if (data.target && data.target.result) {
	        let result = data.target.result;
	        if (
	          typeof result === "string" &&
	          result.includes("code") &&
	          result.includes("msg")
	        ) {
	            result = JSON.parse(data.target.result);
	            this.$message.error(result.msg);
	            return;
	          }
	        }
	       // 是文件
	       let blob = new Blob([res], { type: "application/octet-stream" });
	       // 上方代码有处理导出的文件的代码
	     }
	 }
	 reader.readAsText(new Blob([res], { type: "application/json" })); // 按照json解析
}.catch((err) => {
    console.log('导出失败')
});
     
三、最后:

个人建议能使用proxy/await就用,进行try catch错误拦截,然后做一些错误处理,看到我进行很多的判断也是因为确保数据存在,可能多余,但实际这样做也没问题。

实际会有人觉得返回是乱码,但那其实就是文件二进制流,使用blob或arrayBuffer处理即可。

最后的最后,希望能帮到解决业务问题!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值