java接口下载zip,不生成中间文件,返回前端文件流

java接口下载zip,不生产中间文件,返回前端文件流

    • 程序设计:
    • 代码实现:

程序设计:

前端向后端请求zip文件,zip文件中有多个文件压缩而成,后端操作文件流,而不生成中间文件。最后把zip返回给前端。

代码实现:

    @ApiOperation(value = "下载Zip", notes = "")@PostMapping("/getDownLoadZip")public void getDownLoadZip(@RequestBody GClientManagementVo vo, HttpServletRequest request,HttpServletResponse response) throws Exception {SysUserEntityVo uc = (SysUserEntityVo) request.getAttribute("UC");GClientManagementService.getDownLoadZip(vo, uc,response);}

中间有业务代码,可酌情删减。代码中注意关闭流,避免影响内存。

 @Overridepublic void getDownLoadZip(GClientManagementVo vo, SysUserEntityVo uc, HttpServletResponse response) throws Exception {String filename = vo.getProjectName();String encodeFileName = URLEncoder.encode(filename);ServletOutputStream out = response.getOutputStream();// 创建一个ByteArrayOutputStream来存放最终的ZIP流ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();ZipOutputStream zipOut = new ZipOutputStream(zipOutputStream);try {//写入文件createFilePs(vo, zipOut);//结束写入zipOut.finish();// 最终ZIP流的内容byte[] zipBytes = zipOutputStream.toByteArray();//设置允许跨域的keyresponse.setHeader("Access-Control-Expose-Headers", "Content-Disposition");//文件名有“,”等特殊字符发送到前端会报错,用""括起来解决response.addHeader("Content-Disposition", "attachment;filename=\"" + encodeFileName + "\"");//设置文件大小response.addHeader("Content-Length", "" + zipBytes.length);//设置文件名,避免问题,这个也用""括起来response.setHeader("filename,", "filename=\"" + encodeFileName + "\"");//设置文件类型response.setContentType("application/octet-stream");out.write(zipBytes);out.flush();} catch (Exception e) {throw e;} finally {try {out.close();} catch (Exception e) {throw e;}try {zipOutputStream.close();} catch (Exception e) {throw e;}try {zipOut.close();} catch (Exception e) {throw e;}try {out.close();} catch (Exception e) {throw e;}}}private void createFilePs(GClientManagementVo vo, ZipOutputStream zipOut) throws Exception {// 创建第一个文件install 或者uninstallByteArrayOutputStream file1 = new ByteArrayOutputStream();//install  or uninstallString str1 = "";String fileName1 = "";QueryWrapper<GClientAdmin> queryWrapper = new QueryWrapper();if (vo.getFunction().equalsIgnoreCase(ParamsEnum.Install.getValue())) {queryWrapper.eq("sign", ParamsEnum.Install.getValue());} else {queryWrapper.eq("sign", ParamsEnum.Uninstall.getValue());}queryWrapper.last("limit 1");GClientAdmin gClientAdmin = gClientAdminDao.selectOne(queryWrapper);fileName1 = gClientAdmin.getScriptName();str1 = replaceScriptcode(gClientAdmin.getScriptCode(), vo);try {// 创建ByteArrayOutputStream来模拟文件流writeToFile(file1, str1);// 将每个文件流添加到ZIP流中addToZipFile(fileName1, file1.toByteArray(), zipOut);} catch (IOException ex) {ex.printStackTrace();throw ex;}//多个已经上传文件List<GClientManagementScriptVo> scriptList = vo.getScriptList();if (CollectionUtils.isNotEmpty(scriptList)) {scriptList.forEach(e -> {List<ParamsObject> paramslist = e.getParamslist();if (CollectionUtils.isNotEmpty(paramslist)) {paramslist.forEach(m -> {if (ParamsEnum.File.getValue().equalsIgnoreCase(m.getDataType())) {String str = m.getFileContent();String fileName = m.getFileName();//创建ByteArrayOutputStream来模拟文件流ByteArrayOutputStream file = new ByteArrayOutputStream();try {// 创建ByteArrayOutputStream来模拟文件流writeToFile(file, str);// 将每个文件流添加到ZIP流中addToZipFile(fileName, file.toByteArray(), zipOut);} catch (IOException ex) {ex.printStackTrace();}}});}});}}private String replaceScriptcode(String scriptcode, GClientManagementVo vo) throws Exception {//查找主参数的字符串String startParams = ParamsEnum.Params_Replace_Start.getValue();String endParams = ParamsEnum.Params_Replace_End.getValue();String resultParams = findSubstringBetween(scriptcode, startParams, endParams);if (resultParams != null) {//开始替换主参数String result = resultParams//projectName.replace(ParamsEnum.ProjectName.getValue(), "\"" + vo.getProjectName() + "\"")//applicationName.replace(ParamsEnum.MSIApplicationName.getValue(), "\"" + vo.getApplicationName() + "\"")//cmdRcopt.replace(ParamsEnum.CmdRCOpt.getValue(), vo.getCmdRcopt())//maxRunTime.replace(ParamsEnum.MaxRunTime.getValue(), vo.getMaxRunTime().toString())//startStopService.replace(ParamsEnum.StartStopService.getValue(), "\"" + vo.getStartStopService() + "\"")//debugEnable.replace(ParamsEnum.DebuggingEnabled.getValue(), "$" + vo.getDebugEnable())//defaultMsicLine.replace(ParamsEnum.DefaultMSICmdLine.getValue(), "\"" + vo.getDefaultMsicLine() + "\"")//uDriveMap.replace(ParamsEnum.UDriveMap.getValue(), "$" + vo.getuDriveMap())//function.replace(ParamsEnum.sFunction.getValue(), "\"" + vo.getFunction().toUpperCase(Locale.ROOT) + "\"")//ifsScript.replace(ParamsEnum.bIsIFSScript.getValue(), "$" + vo.getIfsScript());//替换主脚本字符串// 使用 replaceAll 方法和正则表达式来替换所有匹配的子字符串// 注意:这里使用了正则表达式,所以需要对特殊字符进行转义int startIndex = scriptcode.indexOf(startParams);if (startIndex != -1) {int endIndex = scriptcode.indexOf(endParams, startIndex);if (endIndex != -1) {scriptcode = scriptcode.substring(0, startIndex) + result + scriptcode.substring(endIndex + endParams.length());} else {throw new Exception("End tag not found.");}} else {throw new Exception("Start tag not found.");}//查找子参数的字符串String startCommand = ParamsEnum.Command_Replace_Start.getValue();String endCommand = ParamsEnum.Command_Replace_End.getValue();AtomicReference<String> codeStr = new AtomicReference<>("");if (CollectionUtils.isNotEmpty(vo.getScriptList())) {vo.getScriptList().forEach(e -> {AtomicReference<String> finalCode = new AtomicReference<>(e.getScriptCode());if (CollectionUtils.isNotEmpty(e.getParamslist())) {e.getParamslist().forEach(m -> {String value = "";String name = "";if (m.getDataType().equalsIgnoreCase(ParamsEnum.Boolean.getValue())) {value = "$" + m.getValue();name = "${" + m.getName() + "}";} else if (m.getDataType().equalsIgnoreCase(ParamsEnum.String.getValue())) {//CustomParameters特殊情况,全string参数if(m.getName().equalsIgnoreCase(ParamsEnum.CustomParameters.getValue())){if(StringUtils.startsWith(m.getValue().toString(),"\"")&&StringUtils.endsWith(m.getValue().toString(),"\"")){value = m.getValue().toString();}else {value = "\"" + m.getValue() + "\"";}}else {value = "\"" + m.getValue() + "\"";}name = "${" + m.getName() + "}";} else if (m.getDataType().equalsIgnoreCase(ParamsEnum.Int.getValue())) {value = m.getValue().toString();name = "${" + m.getName() + "}";} else if (m.getDataType().equalsIgnoreCase(ParamsEnum.File.getValue())) {value = "\"\\" + m.getFileName() + "\"";name = "${" + m.getName() + "}";}finalCode.set(finalCode.get().replace(name, value));});}codeStr.set(codeStr.get() + "\n" + finalCode.get());});}//子参数替换int startIndex2 = scriptcode.indexOf(startCommand);if (startIndex2 != -1) {int endIndex2 = scriptcode.indexOf(endCommand, startIndex2);if (endIndex2 != -1) {scriptcode = scriptcode.substring(0, startIndex2) + codeStr.get() + scriptcode.substring(endIndex2 + endCommand.length());} else {throw new Exception("End tag not found.");}} else {throw new Exception("Start tag not found.");}} else {throw new Exception("error");}return scriptcode;}public static String findSubstringBetween(String source, String start, String end) {// 找到开始字符串的位置int startIndex = source.indexOf(start);// 开始字符串不存在if (startIndex == -1) {return null;}// 在开始字符串之后找到结束字符串的位置int endIndex = source.indexOf(end, startIndex + start.length());// 结束字符串不存在if (endIndex == -1) {return null;}// 提取并返回子字符串return source.substring(startIndex + start.length(), endIndex);}private void writeToFile(ByteArrayOutputStream out, String content) throws IOException {try (OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) {writer.write(content);writer.flush();} finally {try {out.close();} catch (Exception e) {throw e;}}}private void addToZipFile(String fileName, byte[] fileContent, ZipOutputStream zipOut) throws IOException {ZipEntry zipEntry = new ZipEntry(fileName);zipOut.putNextEntry(zipEntry);zipOut.write(fileContent);zipOut.closeEntry();}

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

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

相关文章

数据结构(ing)

学习内容 指针 指针的定义&#xff1a; 指针是一种变量&#xff0c;它的值为另一个变量的地址&#xff0c;即内存地址。 指针在内存中也是要占据位置的。 指针类型&#xff1a; 指针的值用来存储内存地址&#xff0c;指针的类型表示该地址所指向的数据类型并告诉编译器如何解…

Java网络套接字

在Java的开发中&#xff0c;有一个很重要&#xff01;很重要&#xff01;很重要&#xff01;的东西&#xff0c;叫做网络套接字&#xff0c;它被广泛的用来二次开发服务&#xff0c;比如大数据中台的服务链路调用等。 它的实现原理是依靠三次握手来完成通信的建立&#xff0c;…

Mac 安装Mysql启动Mysql以及数据库的常规操作

Mac 安装Mysql启动Mysql以及数据库的常规操作 一、mysql的安装 1、登录官方网站:dev.mysql.com/downloads/mysql/ 二、查看系统架构 uname -m 在MAC中&#xff1a; 如果输出结果是 x86_64&#xff0c;则表示你的系统是 x86-64 架构。 如果输出结果是 arm64&#xff0c;则表示…

OpenCV的人脸检测模型FaceDetectorYN

OpenCV的人脸检测模型FaceDetectorYN 1. 官网地址2. 如何使用2.1.到opencv_zoo下载模型文件和代码2.2. 下载文件展示2.3. 修改了demo支持读取视频文件&#xff0c;默认是图片和摄像头## 2.4 效果展示 1. 官网地址 https://docs.opencv.org/4.x/df/d20/classcv_1_1FaceDetector…

DeepSeek-VL2

《DeepSeek-VL2: Mixture-of-Experts Vision-Language Models for Advanced Multimodal Understanding》是 DeepSeek-AI 团队发布的关于视觉语言模型 DeepSeek-VL2 的论文&#xff0c;以下是对该论文的详细介绍&#xff1a; 研究背景与动机 多模态理解的重要性&#xff1a;在当…

电子应用设计方案82:智能 AI 椅子系统设计

智能 AI 椅子系统设计 一、引言 智能 AI 椅子旨在为用户提供更加舒适、个性化和智能化的坐乘体验&#xff0c;结合了先进的技术和人体工程学原理。 二、系统概述 1. 系统目标 - 自动适应用户的体型和坐姿&#xff0c;提供最佳的支撑和舒适度。 - 实时监测用户的健康数据&…

Ps:创建数据驱动的图像

在设计实践中&#xff0c;常常需要处理大量内容变化但设计格式统一的任务&#xff0c;例如批量生成名片、工作证、学生证、胸牌、奖状或证书甚至图册。这些工作如果逐一手动制作&#xff0c;不仅耗时费力&#xff0c;还容易出错。 为解决这一问题&#xff0c;Photoshop 提供了强…

彻底解决 Selenium ChromeDriver 不匹配问题:Selenium ChromeDriver 最新版本下载安装教程

在 Python 的 Selenium 自动化测试中&#xff0c;ChromeDriver 是不可或缺的工具。它作为代码与 Chrome 浏览器的桥梁&#xff0c;但如果版本不匹配&#xff0c;就会导致各种报错&#xff0c;尤其是以下常见问题&#xff1a; selenium.common.exceptions.SessionNotCreatedExc…

天猫推荐数据集实践

参考自 https://github.com/xufengtt/recom_teach_code&#xff0c;学习记录。 环境配置&#xff08;maxcomputedataworks&#xff09; 下载天猫推荐数据集&#xff1b;开启 aliyun 的 maxcompute&#xff0c;dataworks&#xff0c;pai&#xff1b;使用 odpscmd 上传本地数据…

人脑处理信息的速度与效率:超越计算机的直观判断能力

人脑处理信息的速度与效率&#xff1a;超越计算机的直观判断能力 关键词&#xff1a; #人脑信息处理 Human Brain Information Processing #并行处理 Parallel Processing #视觉信息分析 Visual Information Analysis #决策速度 Decision Speed #计算机与人脑比较 Computer v…

checked 溢出问题

{try{int i int.MaxValue;int j;checked{j i 1;}}catch (OverflowException er){Console.WriteLine($"加Checked——>{er.Message}");}}{try{int i int.MaxValue;int j;j i 1;}catch (OverflowException er){Console.WriteLine($"没有加Checked——&g…

LabVIEW 使用 Resample Waveforms VI 实现降采样

在数据采集与信号处理过程中&#xff0c;降采样是一种重要的技术&#xff0c;用于在减少数据点的同时保留信号的关键特性&#xff0c;从而降低存储和计算需求。本文通过 LabVIEW 的 Resample Waveforms (continuous).vi 示例&#xff0c;详细介绍如何使用该功能实现波形数据的降…

数字化供应链创新解决方案在零售行业的应用研究——以开源AI智能名片S2B2C商城小程序为例

摘要&#xff1a; 在数字化转型的浪潮中&#xff0c;零售行业正经历着前所未有的变革。特别是在供应链管理方面&#xff0c;线上线下融合、数据孤岛、消费者需求多样化等问题日益凸显&#xff0c;对零售企业的运营效率与市场竞争力构成了严峻挑战。本文深入探讨了零售行业供应…

《计算机网络》(B)复习

目录 一、问答题测试 1.论述具有五层协议的网络体系结构的要点&#xff0c;包括各层的主要功能。 2.物理层的接口有哪几个方面的特性&#xff1f;各包含些什么内容&#xff1f; 3.小明想要访问淘宝&#xff0c;当他打开浏览器输入www.taobao.com浏览淘宝的 过程是什么&#…

用Tkinter制作一个用于合并PDF文件的小程序

需要安装PyPDF2库&#xff0c;具体原代码如下&#xff1a; # -*- coding: utf-8 -*- """ Created on Sun Dec 29 14:44:20 2024author: YBK """import PyPDF2 import os import tkinter as tk import windndpdf_files [] def dragged_files(f…

“大数据+职业本科”:VR虚拟仿真实训室的发展前景

在新时代背景下&#xff0c;随着科技的飞速进步和产业结构的不断升级&#xff0c;职业教育正迎来前所未有的变革。“大数据职业本科”的新型教育模式&#xff0c;结合VR&#xff08;虚拟现实&#xff09;技术的广泛应用&#xff0c;为实训教学开辟了崭新的道路&#xff0c;尤其…

【异常解决】生产环境 net :: ERR_INCOMPLETE_CHUNKED_ENCODING的问题修复

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

矩阵运算提速——玩转opencv::Mat

介绍:用Eigen或opencv::Mat进行矩阵的运算&#xff0c;比用cpp的vector或vector进行矩阵运算要快吗? 使用 Eigen 或 OpenCV 的 cv::Mat 进行矩阵运算通常比使用 std::vector<int> 或 std::vector<double> 更快。这主要有以下几个原因&#xff1a; 优化的底层实现…

mac m2 安装 docker

文章目录 安装1.下载安装包2.在downloads中打开3.在启动台打开打开终端验证 修改国内镜像地址小结 安装 1.下载安装包 到官网下载适配的安装包&#xff1a;https://www.docker.com/products/docker-desktop/ 2.在downloads中打开 拖过去 3.在启动台打开 选择推荐设置 …

redis的集群模式与ELK基础

一、redis的集群模式 1.主从复制 &#xff08;1&#xff09;概述 主从模式&#xff1a;这是redis高可用的基础&#xff0c;哨兵和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的&#xff0c;主负责写入&#xff0c;然后把写入的数据同步到从服务器&#xff…