记一次后端生成Zip文件通过浏览器下载后文件损坏,无法打开,不可预知的末端错误,下载后文件比源文件增大
记一次后端生成Zip文件问题
- 前言
- 问题出现
- 排查
- 一、流没有关好
- 二、写入了空白字节
- 三、没有flush
- 定位环节
- 一、生成
- 二、通过SwaggerUI、PostMan进行下载
- 三、结论
- 解决
- 方法
前言
在项目上线前夕,临时添加了个数据导出的接口,需求是导出压缩包,选择了项目中正常使用的下载接口改造,只是生成文件函数内添加了文件压缩功能
问题出现
但是在其他地方正常下载的接口,下载的压缩包却无法打开,提示
压缩包损坏,不可预料的压缩文件末端,生成的压缩包为205kb,下载后为370kb

排查
通过面向百度,得到几个答案流没关好,写入使用了字节数组导致多写入空字节,流没有flush等
一、流没有关好
1.检查程序输出流是否关闭
2.流的关闭顺序是否正确
但是我的流使用的是try-with-resource方法,不用操作流关闭啊
try (// 1.读取要下载的内容BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));// 将要下载的文件内容通过输出流写到浏览器ServletOutputStream outputStream = response.getOutputStream()) {//do something} catch (IOException e) {e.printStackTrace();}
扩展: 不使用
try-with-resource方法的可以看看这篇文章,避免因为流问题导致
java创建的zip无法打开或打开显示不可预料的压缩文件(https://blog.csdn.net/freedom_zzc/article/details/118930027)
二、写入了空白字节
如果通过流写入时,写入方法不对会出现最后一次写入时,出现空字节写入进文件中,导致文件无法打开,
错误写法:
不能直接用output.write(buffer)。否则如果最后的流不能完全填充buffer时写的字节会比实际的字节多
byte[] b = new byte[2048];int len;while ((len = inputStream.read(b)) > 0) {outputStream.write(b);}
正确写法:
byte[] b = new byte[2048];int len;while ((len = inputStream.read(b)) > 0) {outputStream.write(b, 0, len);}
三、没有flush
如果没有flush流,数据还一直在文件缓冲区,数据还没有被真正的写入到物理介质,如果服务挂掉会出现文件丢失情况。
但是如果直接调用内部的close方法,内部是会先调用flush方法的

其实可以直接使用工具类的拷贝,避免上述问题,而且代码更显简介
hutool包中工具类IoUtil.copy(inputStream, outputStream);

所以我的问题和流没有关系
此时问题陷入了僵局
定位环节
决定排查下看看是哪个环节出问题在进行修改
一、生成
通过手动下载服务器上程序生成的压缩包到本地,打开发现没有问题,不会报错,确定生成环节没有问题,继续往下
二、通过SwaggerUI、PostMan进行下载
通过工具下载,发现文件大小正常,可以正常打开,没有报错,确定下载接口没有问题
三、结论
目前可以确定问题出现在前台调用中,后续通过修改前端调用接口解决了下载压缩包问题
解决
最后解决办法为前台调用接口添加responseType: ‘blob‘参数解决
代码实例如下:
- 前端blob下载,responseType: ‘blob‘(https://blog.csdn.net/weixin_40994437/article/details/122425671)
- 导出文件类型为responseType:blob的问题(https://blog.csdn.net/weixin_43123717/article/details/116125289)
方法
一开始方法就不对,不应该直接就修改后端代码,经验主义害死人,习惯性的以为是写文件出了问题(之前下载word时出现了类似的问题)。应该先定位环节再进行解决问题。
- 首先使用Postman下载或导出文件,如果无法打开,则在后端代码中寻找问题,否则定位前端调用
- 如果服务器本地文件就无法打开,则在生成代码中寻找问题,否则定位下载接口
相关文章:
记一次后端生成Zip文件通过浏览器下载后文件损坏,无法打开,不可预知的末端错误,下载后文件比源文件增大
记一次后端生成Zip文件问题前言问题出现排查一、流没有关好二、写入了空白字节三、没有flush定位环节一、生成二、通过SwaggerUI、PostMan进行下载三、结论解决方法前言 在项目上线前夕,临时添加了个数据导出的接口,需求是导出压缩包,选择了项…...
python中savgol_filter的详细解释
目录savgol_filter简介savgol_filter原理参数window_length对平滑的效果参数polyorder的平滑效果savgol_filter简介 Savitzky-Golay滤波器最初由Savitzky和Golay于1964年提出,是光谱预处理中常用滤波方法,它的核心思想是对一定长度窗口内的数据点进行k阶…...
C语言--指针进阶1
目录回顾字符指针指针数组数组指针&数组名和数组名的区别数组指针的使用指针作为形参练习数组参数、指针参数一维数组传参二维数组传参一级指针传参二级指针传参回顾 指针的内容,我们在初级阶段已经有所涉及了,我们先来复习一下 指针就是个变量&am…...
ssh的使用
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...
Apache Hadoop生态-目录汇总-持续更新
目录 1:系统服务分布图 3台分布式架构 1台单机架构 服务版本介绍 2:服务目录 存储相关 数据采集 任务调度 即席查询 数据可视化 集群监控 元数据管理 用户认证 权限管理 第三方windows客户端 1:系统服务分布图 3台分布式架构…...
「JVM 编译后话」编译器优化技术
后端编译(即时编译、提前编译)的目标时将字节码翻译成本地机器码,而难点是输出优化质量较高的机器码; 文章目录1. 优化技术概览2. 方法内联(Inlining)3. 逃逸分析(Escape Analysis)4…...
【python学习笔记】:输出与输入
01 输出方式 表达式语句、print()函数和使用文件对象的write()方法。 02 输出形式 格式化输出str.format()函数、转成字符串可以使用repr()或str()函数来实现。 (1)repr():产生一个解释器易读的表达形式,便于字符串的拼接。 例:输出平方与…...
汽车电子社区交流宣传
http://t.csdn.cn/VSLO0http://t.csdn.cn/VSLO0 当今的汽车行业已经进入了数字化时代,汽车电子软件的开发变得越来越重要。在这个领域,开发者们需要应对各种挑战,包括复杂的硬件和软件交互、高效的嵌入式编程和安全性要求。为了帮助汽车电子…...
String、StringBuilder 和 StringBuffer 详解
碎碎念 这是一道老生常谈的问题了,字符串是不仅是 Java 中非常重要的一个对象,它在其他语言中也存在。比如 C、Visual Basic、C# 等。字符串使用 String 来表示,字符串一旦被创建出来就不会被修改,当你想修改StringBuffer 或者是 …...
windows服务器上传文件解决方案
1.说明 1.如果上传到linux系统,通常使用ftp相关技术,配合windows端的ftp客户端工具比如FileZilla等进行大文件的上传工作。 2.同理windows服务器也可以开启ftp服务用来传输大文件。 3.本文介绍偷懒方式(常规是开启windows的ftp服务࿰…...
Android Studio翻译插件推介(Translation)
前言 Android Studio翻译插件适合英语水平不太好的程序员(比如:我),最常用的翻译插件Translation和AndroidLocalize,本文主要讲解Translation,亲测可用。 先看看效果:这里是Android的API,任意选…...
DNS,DNS污染劫持,DNS加密
1. DNS(Domain Name System)DNS(Domain Name System), 也叫网域名称系统,是互联网的一项服务。它实质上是一个 域名 和 IP 相互映射的分布式数据库.DNS(Domain Name Server,域名服务…...
【Python】如何度量优秀代码——静态分析工具
静态分析工具背景有哪些静态分析工具呢度量Python代码的静态属性度量Python的生态系统代码的坏味道在类层面上在方法层面上结语背景 静态代码分析工具能够提炼出丰富的代码静态属性信息,这使得程序员可以对代码的复杂性、可修改性和可读性有进一步的了解。 有哪些…...
Open3D 点云高程归一化(基于2维地面点,Python版本)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 之前的博客中Open3D 点云高程归一化(基于地面点,Python版本)是基于三维空间进行最近地面点的查询操作,这里对其进行修改一下,将点云投影到水平面,基于二维空间进行最近地面点的查询,这种方式对一些较为陡峭的…...
动态系统的建模与分析
前言 CS小菜鸡控制理论入门 视频学习笔记 视频传送门:动态系统的建模与分析】9_一阶系统的频率响应_低通滤波器_Matlab/Simulink分析 拉普拉斯变换 F(s)L{f(t)}∫0∞f(t)e−stdtF(s)\mathcal{L}\{f(t)\}\int_0^\infty f(t)e^{-st}\mathrm{d}tF(s)L{f(t)}∫0∞f(t)…...
QCC51XX---HCI log
高通在新的S3/S5以及往后新的平台上面,引入了一个新的调试功能。就是标题说的HCI log,他类似air trace那样用来分析蓝牙协议的,这样我们就可以很详细地找到通信协议之间哪个部分出了问题。以前我们都是通过抓包器抓air trace分析的,抓包器一个要几十万,学会这个功能就相当…...
Redis四 原理篇
《Redis四 原理篇》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Redis四 原理篇》《Redis四 原理篇》1、原理篇-Redis数据结构1.1 Redis数据结构-动态字符串1.2 Redis数据结构-intset1.3 Redis数据结构-Dict1.4 Redis数据结构-ZipList1.4.1 Redis数据…...
从0开始写Vue项目-Vue实现数据渲染和数据的增删改查
从0开始写Vue项目-环境和项目搭建_慕言要努力的博客-CSDN博客从0开始写Vue项目-Vue2集成Element-ui和后台主体框架搭建_慕言要努力的博客-CSDN博客从0开始写Vue项目-Vue页面主体布局和登录、注册页面_慕言要努力的博客-CSDN博客从0开始写Vue项目-SpringBoot整合Mybatis-plus实现…...
AI技术的发展,人工智能对我们的生活有那些影响?
人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一…...
Unity中的Mathf数学运算讲解(值得收藏)
Unity中的Mathf数学运算有哪些? Mathf.Abs(f)绝对值 计算并返回指定参数 f 绝对值 例如: // 输出 10 Debug.log(Mathf.Abs(-10)) Debug.log(Mathf.Abs(10))Mathf.Sin正弦 static function Sin (f : float) : float 计算并返回以弧度为单位指定的角 f 的…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...
