42 ajax 下载文件未配置 responseType blob 导致的文件异常

news2024/11/26 17:00:11

前言

这是一个最近的关于文件下载碰到的一个问题 

主要的情况是, 基于 xhr 发送请求, 获取下载的文件 

然后 之后 xhr 这边拿到 字节序列之后, 封装 blob 来进行下载 

然后 最开始我们这边没有配置 responseType 为 blob, arraybuffer, 然后 导致下载出来的 文件大小超过了一倍,m 并且解压出现了问题 

然后 增加了 responseType 配置为 blob 之后, 文件下载的功能就正常了 

这里来大致看一下 大体的一个情况, 因为 xhr 这边具体的 编码 response, responseText, responseXml 的代码查看不了, 因此看不到 字节序列 转换为 字符串的过程, 因此 这里的结论仅仅是一个 大致的推导

另外 js 这边 new Blob 的具体的代码 也是查看不了, 因此 查看不了 字符串 转换为 字节序列 的这个过程

 

 

测试用例

客户端这边发送请求的 demo 代码如下 

  ajax({
    method: 'post',
    url: '/xxx/file/batchDownload',
    data: data,
    // responseType: 'arraybuffer'
  }).then(res => {
	let blob = new Blob([res], {type: "application/zip"});
	const link = document.createElement("a");
	link.download = 'file.zip';
	link.style.display = "none";
	link.href = URL.createObjectURL(blob);
	document.body.appendChild(link);
	link.click();
	URL.revokeObjectURL(link.href);
	document.body.removeChild(link);
  }).finally(() => {
	this.setdownLoading(row, false)
  })

 

 

正常的情况

如下是一个列表展示, 原始正确的 zip 文件大小为 811667 字节 

// 原始文件大小 
blob 
	811667 
	
// 原始字节序列 使用给定的编码编码为字符序列, 然后再使用相同的编码解码为字节序列 
new String(baos.toByteArray(), $charset).getBytes($charset)
	gbk : 810632 
	utf8 : 1475674 

// 前端 xhr 代码中不配置 responseType 为 arraybuffer/blob 的情况 
xhr, without responseType blob, new Blob([res], {type: "application/zip"});
1476964

 

服务器这边响应的正常的 zip 文件大小如下, 是正确的, 可以正常打开 

f8e920720ead432db262d726bfd4443a.png

 

然后 我们看一下 正常的情况, 即 ajax 增加 responseType 为 blob/arraybuffer 的情况 

这里是 axios 中的基于 xhr 的一个适配器, 这里是具体的基于 XmlHttpRequest 发送请求的地方 

我们可以看到 response 为 blob, 然后 字节数为 811667 拿到的是正常的数据 

011045c7d5a246159862b19cb79be9cc.png

 

然后 进而再外层 业务 handle 处理的时候 也是拿到的正确的数据

然后 最终下载的压缩包, 正常 

631b159d4309404ab346a7a94d77a373.png

 

 

异常的情况

然后 这里可以看到的是 responseData 是一个字符串, 说明 他已经被转换过了 

因为 服务器那边传输的是原始的字节序列, 然后 这里被转换过了之后 可能会造成 字节序列 的数据丢失, 错误 

可以看到 这里数据大小是 1.5M 大概是原始数据的两倍, 字节转字符的编码可能是 gbk 或者 utf8

ec426fe35cc74bd4b0ee15ab0b4bfb8b.png

 

然后 业务这边再根据 字符串传唤为字节序列, 存放到 blob, 拿到的也是一个错误的数据 

可以看到这里数据量大小为 1476944 和上面表格统计的大小基本一致, 之所以说基本一致, 是因为多次下载 会有少许不同, 大小差距在 20字节左右 

c5e215cb58114cb2859ff525b5ba0d55.png

 

所以 综上问题就在于在这个 字节序列 转 字符序列 再转 字节序列 的过程中造成了数据的错误

这个过程 会经过两次字符编码体系的处理

  1. 如果这两次都是 相同的单字节编码, 那么不会出现问题
  2. 如果是两次都是 相同的多字节编码 则可能存在问题, 因为 目标字节序列 可能未必复合目标编码的格式约束, 然后 造成了数据的不可逆丢失
  3. 如果是两次是 不同的编码, 并且存在兼容的 codepoint, 而且 字节序列 中的数据均在这些兼容的 codepoint 范围内, 则不会出现问题, 否则 会出现数据错误

但是 目标字节序列, 是 zip 格式, 任何一个字节的错误 都可能造成整体文件 不符合 zip 的规范, 或者 最开始 验签的时候 就校验不通过

 

 

字节序列 使用 utf8编码转换为字符串, 然后再依据utf8编码转换为字节序列, 数据会不会丢失?

// 原始文件大小 
blob 
	811667 
	
// 原始字节序列 使用给定的编码编码为字符序列, 然后再使用相同的编码解码为字节序列 
new String(baos.toByteArray(), $charset).getBytes($charset)
	gbk : 810632 
	utf8 : 1475674 

 

这里我们先来看下 这里例子中的文件的情况, 这里就解释了 不配置 responseType 为 arraybuffer/blob 的情况下下载出来的数据是错误的问题 

使用 utf8 的时候, 整个过程最终结果的字节序列长度为 1475674

9a21c8df869f4c10a866837678bc8694.png

 

使用 gbk 的时候, 整个过程最终结果的字节序列长度为 810632

ef3a7ab8f1da4e1aa0d2cf642a9157b0.png

 

然后 我们这里来看拿一下 上面的转换之后, 什么情况下 数据会丢失? 什么情况下 数据不丢失? 

如果 字节序列是满足 utf8 的编码规范, 则数据不会丢失, 否则 可能会有数据丢失

比如这里是原始字节序列 不满足 utf8 的编码规范, 然后 造成了数据的丢失, 原始 仅仅有 6 个字节, 转换之后却有 18 个字节, 并且 数据还存在错误

b68040b63ef2412eb288a1d544c27495.png

 

比如这里是原始字节序列 满足 utf8 的编码规范, 然后 可以看到的是 原始字节序列 和 目标字节序列 是相同的

222953164db24c58bf507f42be8baa43.png

 

 

但是我们的目标文件是一个 zip 格式的二进制文件, 我们不能确保它的字节序列满足 固定的字符编码[假设浏览器这边是以 utf8 进行编码解码] 

所以 如果是存在一个这个转换过程的话, 是可能存在 字节序列的数据的错误, 丢失 

进而 导致 下载下来的文件, zip 解压缩软件 识别出错

355f358219e7454197a1f77ab798d7d5.png

 

 

完 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1554185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

许可型DeFi 项目NEOPIN:在合规的框架下推动DeFi的创新

合规化已成 DeFi 的主流方向 过去的几年里,全球金融市场见证了 DeFi 的快速增长。DeFi 通过提供无需中介的交易和借款等金融服务,为用户带来前所未有的便利。然而,其匿名性和去中心化的特性也为监管和安全带来挑战 —— DeFi项目的透明度不足…

机器学习概论—增强学习

机器学习概论—增强学习 强化学习(Reinforcement Learning, RL)或者说是增强学习,是机器学习的一个领域,旨在使智能体通过与环境的交互学习如何做出决策,它是关于在特定情况下采取适当的行动来最大化奖励。它被各种软件和机器用来寻找在特定情况下应采取的最佳行为或路径…

马上蓝桥杯了,干货总结动态规划专题,祝你考场爆杀(基础篇)猫粮规划 接苹果 魔族密码 最大正方形 最大正方形 2 奶牛比赛

目录 猫粮规划 思路: 接苹果 思路: 魔族密码 思路: 最大正方形 思路: 最大正方形 2 思路: 奶牛比赛 ​编辑 思路: 猫粮规划 思路: 每种食物都有两种状态,记忆化d…

以太网/USB 数据采集卡 24位16通道 labview 256K同步采样

XM7016以太网SUB数据采集卡 XM7016是一款以太网/USB高速数据采集卡,具有16通道真差分输入,24位分辨率,单通道最高采样率256ksps. 16通道同步共计4.096Msps、精密前置增益放大、集成IEPE/ICP硬件支持的特点。本产品采用了多个高精度24位ADC单元…

<QT基础(4)>QLabel使用笔记

Label 前面的文章里面把QLabel批量引入ScrollArea作为预览窗口,这篇把图像填充到QLable的PixelMap展示指定图像。 参数设置 设置QLabel的大小格式 QWidget* widget new QWidget; widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); widget->…

31-5 命令执行漏洞 - RCE漏洞利用

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、打开pikachu靶场 二、远程命令执行利用 正常情况下这一关卡就是个ping命令,我们只能输入个 ip 靶场就就会ping 这ip 但是我们可以用管道符拼接来执行其他命令,详细可以看我…

每日一题 --- 快乐数[力扣][Go]

快乐数 题目:202. 快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到…

正弦实时数据库(SinRTDB)的使用(5)-历史数据查询

前文已经将正弦实时数据库的使用进行了介绍,需要了解的可以先看下面的博客: 正弦实时数据库(SinRTDB)的安装 正弦实时数据库(SinRTDB)的使用(1)-使用数据发生器写入数据 正弦实时数据库(SinRTDB)的使用(2)-接入OPC DA的数据 正弦实时数据库(SinRTDB)…

全国产数据采集卡定制,24位八通道以太网数据采集卡 labview 100K采样

XM702是一款以太网型高速数据采集卡,具有8通 道真差分输入,24位分辨率,单通道最高采样率100ksps八通 道同步共计800ksps、精密前置增益放大、集成IEPE/ICP硬件 支持的特点。本产品采用了多个高精度24位ADC单元及配合本 公司多年积累开发的前置…

Linux: 检测工具: monit: cpu占用率的一个例子

最近看到monit使用的CPU有时候会突然的增加,通过perf查看,可以看到是下面这个函数调用占用的比较高。 Overhead Comma Shared Object Symbol 29.72% monit [kernel.kallsyms] [k] __d_lookup__d_lookup29.65% d_lookup proc_fill_cache ` proc_readfd_common iterate_dir ksy…

(2024,嵌套标记化,区域编码器,上下文编码器,Transformer-XL,Mamba)xT:大图像中更大上下文的嵌套标记化

xT: Nested Tokenization for Larger Context in Large Images 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 3. 背景 3.1. 长上下文模型作为上下文编码器 3.2. 线性注意机…

2024年妈妈杯数学建模思路B题思路分享

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间:2024…

如何在 Oracle 中使用 CREATE SEQUENCE 语句

在本文中,我们将讨论 Oracle CREATE SEQUENCE 语句,其主要目的是提供一种可靠的方法来生成唯一且连续的数值,通常用于数据库表中的主键字段。此功能对于维护数据完整性和效率、确保不同记录之间的标识符有序分配尤其重要。从本质上讲&#xf…

数据库的横表和竖表

先来看个图: 定义如下: 横表:在一行数据中包含了所有的属性,一行就代表了一个完整的实体 竖表:在一行中只存储一个实体的一个属性,多个行组合在一起才组成一个完整的属性适用场景: 横表:对查…

从零玩转CanMV-K230(2)-开发环境搭建

文章目录 前言一、编译环境搭建二、镜像烧写总结 前言 本章介绍如何搭建CanMV-K230开发环境,基于LinuxRT-smart双系统开发 一、编译环境搭建 我是用的vmware虚拟机:ubuntu 20.04,搭建环境如下: 直接下载压缩包,下载…

【CTFshow 电子取证】套的签到题

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收…

一、JAVA集成海康SDK

JAVA集成海康SDK 文章目录 JAVA集成海康SDK前言一、项目依赖 jar1. examples.jar2. 项目依赖 jna.jar,可以通过 maven依赖到。二、集成SDK1.HcNetSdkUtil 海康 SDK封装类2.HCNetSDK3.Linux系统集成SDK三、总结前言 提示:首先去海康官网下载 https://open.hikvision.com/dow…

56、FreeRTOS/GPIO与定时器相关学习20240329

一、代码实现控制开发板上的指示灯闪烁。 /* USER CODE BEGIN 0 */ //利用定时器机制 定时器溢出时对应的回调函数实现如下 //本次实现控制PB0,PB1两个灯 int flag1 0,flag2 0;//使用一个标记执行以下代码 会造成一个灯常亮 另一个常灭 void HAL_TIM_PeriodElaps…

vue3+ts白屏问题解决

文章目录 打开白屏解决方法可能出现问题使用base导致的使用baseUrl导致的 注意点vue3ts白屏问题知识分享 打开白屏 解决方法 在vue.config.js页面 添加publicPath:./, const { defineConfig } require(vue/cli-service)module.exports defineConfig({ transpileDependenci…

Nginx-记

Nginx是一个高性能的web服务器和反向代理服务器,用于HTTP、HTTPS、SMTP、POP3和IMAP协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。 (1)更快 这表现在两个方面:一方面,在正常情况下&…