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.mzph.cn/bicheng/66018.shtml

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

相关文章

职场常用Excel基础04-二维表转换

大家好&#xff0c;今天和大家一起分享一下excel的二维表转换相关内容~ 在Excel中&#xff0c;二维表&#xff08;也称为矩阵或表格&#xff09;是一种组织数据的方式&#xff0c;其中数据按照行和列的格式进行排列。然而&#xff0c;在实际的数据分析过程中&#xff0c;我们常…

python-redis访问指南

Redis&#xff08;Remote Dictionary Server&#xff09;是一种开源的内存数据结构存储&#xff0c;可用作数据库、缓存和消息代理。它功能强大且灵活&#xff0c;可根据需求调整架构和配置&#xff0c;以高性能、简单易用、支持多种数据结构而闻名&#xff0c;广泛应用于各种场…

Px4 V2.4.8飞控Mavlink命令控制说明

首先&#xff0c;可以使用两种方法连接飞控&#xff0c;使用虚拟机&#xff08;LINUX&#xff09;或使用地面站&#xff08;QGC&#xff09;连接。 在px4的代码文件位置打开命令终端&#xff0c;输入连接命令&#xff1a; ./Tools/mavlink_shell.py 在控制台使用help来获取所有…

MySQL8安装与卸载

1.下载mysql MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压mysql安装包 解压到自己定义的目录&#xff0c;这里解压就是安装&#xff0c;解压后的路径不要有空格和中文。 3.配置环境变量 配置环境变量可以方便电脑在任何的路径…

简洁安装配置在Windows环境下使用vscode开发pytorch

简洁安装配置在Windows环境下使用vscode开发pytorch 使用anaconda安装pytorch&#xff0c;通过vscode集成环境开发pytorch 下载 anaconda 下载网址&#xff0c;选择对应系统的版本 https://repo.anaconda.com/archive/ windows可以选择Anaconda3-2024.10-1-Windows-x86_64.e…

使用 Jupyter Notebook:安装与应用指南

文章目录 安装 Jupyter Notebook1. 准备环境2. 安装 Jupyter Notebook3. 启动 Jupyter Notebook4. 选择安装方式&#xff08;可选&#xff09; 二、Jupyter Notebook 的基本功能1. 单元格的类型与运行2. 可视化支持3. 内置魔法命令 三、Jupyter Notebook 的实际应用场景1. 数据…

unity学习3:如何从github下载开源的unity项目

目录 1 网上别人提供的一些github的unity项目 2 如何下载github上的开源项目呢&#xff1f; 2.1.0 下载工具 2.1.1 下载方法1 2.1.2 下载方法2&#xff08;适合内部项目&#xff09; 2.1.3 第1个项目 和第4项目 的比较 第1个项目 第2个项目 第3个项目 2.1.4 下载方法…

npm install --global windows-build-tools --save 失败

注意以下点 为啥下载windows-build-tools&#xff0c;是因为node-sass4.14.1 一直下载不成功&#xff0c;提示python2 没有安装&#xff0c;最终要安装这个&#xff0c;但是安装这个又失败&#xff0c;主要有以下几个要注意的 1、node 版本 14.21.3 不能太高 2、管理员运行 …

十二、Vue 路由

文章目录 一、简介二、安装与基本配置安装 Vue Router创建路由实例在应用中使用路由实例三、路由组件与视图路由组件的定义与使用四、动态路由动态路由参数的定义与获取动态路由的应用场景五、嵌套路由嵌套路由的概念与配置嵌套路由的应用场景六、路由导航<router - link>…

NLP 中文拼写检测纠正论文-08-Combining ResNet and Transformer

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

儿童坐姿矫正器是如何实现语音提示功能?

儿童坐姿不正确&#xff0c;不仅影响他们的体态美观&#xff0c;更关乎其身体健康与成长发育。长期以往&#xff0c;可能会导致脊柱侧弯、近视加深等一系列健康问题。家长应当对此给予足够重视&#xff0c;及时纠正孩子们的坐姿习惯。 为了改善这一状况&#xff0c;可以从这方…

【蓝桥杯——物联网设计与开发】Part1:GPIO

目录 一、GPIO输出——LED &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;驱动原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#x1f7e2;️main 函数 &#xff08;4&#xff09;实验现象 二…

小程序发版后,强制更新为最新版本

为什么要强制更新为最新版本&#xff1f; 在小程序的开发和运营过程中&#xff0c;强制用户更新到最新版本是一项重要的策略&#xff0c;能够有效提升用户体验并保障系统的稳定性与安全性。以下是一些主要原因&#xff1a; 1. 功能兼容 新功能或服务通常需要最新版本的支持&…

Servlet解析

概念 Servlet是运行在服务端的小程序&#xff08;Server Applet)&#xff0c;可以处理客户端的请求并返回响应&#xff0c;主要用于构建动态的Web应用&#xff0c;是SpringMVC的基础。 生命周期 加载和初始化 默认在客户端第一次请求加载到容器中&#xff0c;通过反射实例化…

太速科技-633-4通道2Gsps 14bit AD采集PCie卡

4通道2Gsps 14bit AD采集PCie卡 一、板卡概述 二、性能指标 板卡功能 参数 内容 ADC 芯片型号 AD9689 路数 4路ADC&#xff0c; 采样率 2Gsps 数据位 14bit 数字接口 JESD204B 模拟接口 交流耦合 模拟输入 1V 连接器 6路 SMA 输入阻抗 50Ω 模拟指…

戴尔/Dell 电脑按什么快捷键可以进入 Bios 设置界面?

BIOS&#xff08;基本输入输出系统&#xff09;是计算机硬件与操作系统之间的桥梁&#xff0c;它负责初始化和测试系统硬件组件&#xff0c;并加载启动操作系统。在某些情况下&#xff0c;如调整启动顺序、更改系统时间或日期、修改硬件配置等&#xff0c;您可能需要进入BIOS进…

分类模型评估利器-混淆矩阵

相关文章 地理时空动态模拟工具介绍&#xff08;上&#xff09; 地理时空动态模拟工具介绍&#xff08;下&#xff09;地理时空动态模拟工具的使用方法 前言 混淆矩阵&#xff08;Confusion Matrix&#xff09;是机器学习领域中用于评估分类模型性能的一种工具。它通过矩阵的…

贪心算法概述

贪心算法总是作出当前看来最好的选择&#xff0c;是局部最优 可以使用贪心算法的问题一般具有两个重要的性质 贪心选择性质最优子结构性质 贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择来达到 其与动态规划的问题区别在于&#xff0c;动态规划算法通…

Unity-Mirror网络框架-从入门到精通之Basic示例

文章目录 前言Basic示例场景元素预制体元素代码逻辑BasicNetManagerPlayer逻辑SyncVars属性Server逻辑Client逻辑 PlayerUI逻辑 最后 前言 在现代游戏开发中&#xff0c;网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架&#xff0c;专为多人…

wx015基于springboot+vue+uniapp的经济新闻资讯的设计与实现

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…