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

前言

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

主要的情况是, 基于 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.rhkb.cn/news/290126.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

语音模块摄像头模块阿里云结合,实现垃圾的智能识别

语音模块&摄像头模块&阿里云结合 文章目录 语音模块&摄像头模块&阿里云结合1、实现的功能2、配置2.1 软件环境2.2 硬件配置 3、程序介绍3.1 程序概况3.2 语言模块SDK配置介绍3.3 程序文件3.3.1 开启摄像头的程序3.3.2 云端识别函数( Py > C ) & 串口程序…

Flask学习(六):蓝图(Blueprint)

蓝图(Blueprint):将各个业务进行区分,然后每一个业务单元可以独立维护,Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的。 Demo目录结构&#xf…

基于js css的瀑布流demo

要实现照片按照瀑布流展示&#xff0c;写个小demo&#xff0c;记录下。 瀑布流实现思路如下&#xff1a; CSS 弹性布局对 3 列按横向排列&#xff0c;对每一列内部按纵向排列 html代码&#xff1a; <div class"content"></div> css代码&#xff1a; …

2.4 比较检验 机器学习

目录 常见比较检验方法 总述 2.4.1 假设检验 2.4.2 交叉验证T检验 2.4.3 McNemar 检验 接我们的上一篇《性能度量》&#xff0c;那么我们在某种度量下取得评估结果后&#xff0c;是否可以直接比较以评判优劣呢&#xff1f;实际上是不可以的。因为我们第一&#xff0c;测试…

Unity 实现鼠标左键进行射击

发射脚本实现思路 分析 确定用户交互方式&#xff1a;通过鼠标左键点击发射子弹。确定子弹发射逻辑&#xff1a;每次点击后有一定时间间隔才能再次发射。确定子弹发射源和方向&#xff1a;子弹从枪口&#xff08;Transform&#xff09;位置发射&#xff0c;沿枪口方向前进。 变…

iOS客户端自动化UI自动化airtest+appium从0到1搭建macos+脚本设计demo演示+全网最全最详细保姆级有步骤有图

Android客户端自动化UI自动化airtest从0到1搭建macos脚本设计demo演示全网最全最详细保姆级有步骤有图-CSDN博客 避坑系列-必读&#xff1a; 不要安装iOS-Tagent &#xff0c;安装appium -这2个性质其实是差不多的都是为了安装wda。注意安装appium最新版本&#xff0c;安装完…

Gitlab CI---could not read username for xxx: no such device or address

0 Preface/Foreword 项目开发中&#xff0c;经常会使用第三方的算法或者功能&#xff0c;那么就需要把对应的repo以子模块的方式添加到当前repo中。 添加命令&#xff1a; git submodule add <URL> 1 问题表现 子模块添加成功&#xff0c;但是GitLab CI阶段&#xff…

基于Python的电商特产数据可视化分析与推荐系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 利用网络爬虫技术从某东采集某城市的特产价格、销量、评论等数据&#xff0c;经过数据清洗后存入数据库&#xff0c;并实现特产销售、市场占有率、价格区间等多维度的可视化统计分析&#xff0c;并…

filebox在线文件管理工具V1.11.1.1查分吧修改自用版免费分享[PHP]

* 基于:https://down.chinaz.com/soft/35899.htm * 查分吧 修改自用版今日对外分享(自2016年1.10版本以来一直用他云开发:Web环境即时看效果) * 也可以用于本人很多txt/csv通用查询系统的在线管理后台管理数据 * 默认登陆账号filebox密码nidemima * 修改账号密码:21-22行;获取…

Python人工智能:气象数据可视化的新工具

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…

MySQL进阶-----索引的语法与SQL性能分析

目录 前言 一、索引语法 1.SQL语法 2.案例演示 二、SQL性能分析 三、慢查询日志 1.开启日志 2.测试样例 四、profile详情 1.开启profile 2.profile测试SQL语句 五、explain详情 1.语法结构 2.执行顺序示例&#xff08;id&#xff09; 3.执行性能示例(type) 前言 本…

fastadmin学习04-一键crud

FastAdmin 默认内置一个 test 表&#xff0c;可根据表字段名、字段类型和字段注释通过一键 CRUD 自动生成。 create table fa_test (id int unsigned auto_increment comment ID primary key,user_id int(10) default 0 null…

蓝桥杯物联网遇见的重大BUG及其产生原因和解决方法

BUG列表 1、ADC的RP2显示一直为0&#xff1a;2、LORX_Tx发送数据乱码&#xff1a;3、strcmp比较char a[2] {1, 2}与“12”字符串是否相等板子会死机&#xff1a;4、LORA_Tx和LORA_Rx放一起会接收不到数据&#xff1a;5、RTC获取到静止时间&#xff1a;6、ADC获取RP1和RP2模拟量…

Vue 03 组件通信

Vue学习 Vue 0301 浏览器本地存储localStorageSessionStorage案例 todolist的完善 02 组件自定义事件Custom Events基本使用解绑自定义事件注意事项①② 总结案例 todolist的完善 03 全局事件总线GlobalEventBus案例 todolist的完善 04 消息的订阅与发布案例 todolist的完善 05…

网络原理-传输层-UDP报文结构

本文介绍UDP报文 有很多友友搞不清楚UDP报文的详细结构还有TCP的详细结构,所以专门分开来讲 以免弄混. 首先我们先看一下整个UDP结构,让大家有一个全方面的认识 下面我们来详细解释UDP报 16位源端口号(本机):就是2字节大小,16个二进制位. 16位目的端口号(目的机):也是2字节…

SQL Server 数据库常见提权总结

前面总结了linux和Windows的提权方式以及Mysql提权&#xff0c;这篇文章讲讲SQL Server数据库的提权。 目录 基础知识 权限判定 系统数据库 存储过程 常见系统存储过程 常见扩展存储过程 xp_cmdshell扩展存储过程提权 xp_dirtree写入文件提权 sp_oacreate提权 xp_re…

Linux安装redis(基于CentOS系统,Ubuntu也可参考)

前言&#xff1a;本文内容为实操记录&#xff0c;仅供参考&#xff01; 一、下载并解压Redis 1、执行下面的命令下载redis&#xff1a;wget https://download.redis.io/releases/redis-6.2.6.tar.gz 2、解压redis&#xff1a;tar xzf redis-6.2.6.tar.gz 3、移动redis目录&a…

和数集团董事长唐毅一行参加香港加密峰会

2024年3月26日-27日&#xff0c;和数集团董事长唐毅、UM Company CEO Rubens、QUANTIX CAPITAL风险投资基金CEO Jake一行&#xff0c;参加了亚太地区重要的Web3会议“WOW Summit HongKong 2024”。 UM Company CEO Rubens、和数集团董事长唐毅、QUANTIX CAPITAL风险投资基金 CE…

【Java八股面试系列】中间件-Redis

目录 Redis 什么是Redis Redis解决了什么问题 Redis的实现原理 数据结构 String 常用命令 应用场景 List(列表) 常用命令 应用场景 Hash(哈希) 常用命令 应用场景 set(集合) 常见命令​编辑 应用场景 Sorted Set(有序集合) 常见命令​编辑 应用场景 数据持…

Day46:WEB攻防-注入工具SQLMAPTamper编写指纹修改高权限操作目录架构

目录 数据猜解-库表列数据&字典 权限操作-文件&命令&交互式 提交方法-POST&HEAD&JSON 绕过模块-Tamper脚本-使用&开发 分析拓展-代理&调试&指纹&风险&等级 知识点&#xff1a; 1、注入工具-SQLMAP-常规猜解&字典配置 2、注入…