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

news2025/1/7 16:21:12

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);
    }

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

 @Override
    public 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();

            //设置允许跨域的key
            response.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 或者uninstall
        ByteArrayOutputStream file1 = new ByteArrayOutputStream();
        //install  or uninstall
        String 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.coloradmin.cn/o/2271993.html

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

相关文章

【USRP】教程:在Macos M1(Apple芯片)上安装UHD驱动(最正确的安装方法)

Apple芯片 前言安装Homebrew安装uhd安装gnuradio使用b200mini安装好的路径下载固件后续启动频谱仪功能启动 gnu radio关于博主 前言 请参考本文进行安装&#xff0c;好多人买了Apple芯片的电脑&#xff0c;这种情况下&#xff0c;可以使用UHD吗&#xff1f;答案是肯定的&#…

多媒体素材库系统

本文结尾处获取源码。 本文结尾处获取源码。 本文结尾处获取源码。 一、相关技术 后端&#xff1a;Java、JavaWeb / Springboot。前端&#xff1a;Vue、HTML / CSS / Javascript 等。数据库&#xff1a;MySQL 二、相关软件&#xff08;列出的软件其一均可运行&#xff09; I…

EdgeX规则引擎eKuiper

EdgeX 规则引擎eKuiper 一、架构设计 LF Edge eKuiper 是物联网数据分析和流式计算引擎。它是一个通用的边缘计算服务或中间件,为资源有限的边缘网关或设备而设计。 eKuiper 采用 Go 语言编写,其架构如下图所示: eKuiper 是 Golang 实现的轻量级物联网边缘分析、流式处理开源…

即插即用,无痛增强模型生成美感!字节跳动提出VMix:细粒度美学控制,光影、色彩全搞定

文章链接&#xff1a;https://arxiv.org/pdf/2412.20800 代码地址&#xff1a;https://github.com/fenfenfenfan/VMix 项目地址&#xff1a;https://vmix-diffusion.github.io/VMix/ 亮点直击 分析并探索现有模型在光影、色彩等细粒度美学维度上生成图像的差异&#xff0c;提出…

I.MX6ull-PWM

一、PWM介绍 PWM&#xff08;Pulse Width Modulation&#xff09;简称脉宽调制&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的 一种非常有效的技术&#xff0c;广泛应用在测量、通信、工控等方面。 pwm的工作电路 它的四种时钟信号 (1)High-frequency referenc…

性能测试04|JMeter:连接数据库、逻辑控制器、定时器

目录 一、连接数据库 1、使用场景 2、直连数据库的关键配置 3、案例 ​编辑 二、逻辑控制器 1、if控制器 2、循环控制器 3、ForEach控制器 三、定时器 1、同步定时器 2、常数吞吐量定时器&#xff08;用的少&#xff0c;了解即可&#xff09; 3、固定定时器 一、连…

基于SpringBoot和OAuth2,实现通过Github授权登录应用

基于SpringBoot和OAuth2&#xff0c;实现通过Github授权登录应用 文章目录 基于SpringBoot和OAuth2&#xff0c;实现通过Github授权登录应用0. 引言1. 创建Github应用2. 创建SpringBoot测试项目2.1 初始化项目2.2 设置配置文件信息2.3 创建Controller层2.4 创建Html页面 3. 启动…

Visual Studio C++使用笔记

个人学习笔记 右侧项目不显示 CTRL ALT L 创建第一个项目 添加类&#xff08;头文件、CPP文件&#xff09;

USB射频微波功率计的功能与优势-盛铂科技

USB射频功率计是一种用于测量射频信号&#xff08;RF&#xff09;功率的仪器&#xff0c;它通过USB接口与计算机或其他设备连接&#xff0c;以便于进行数据采集、处理和显示。 主要功能 功率测量&#xff1a;能够测量射频信号的功率&#xff0c;通常以毫瓦&#xff08;mW&…

百度贴吧的ip属地什么意思?怎么看ip属地

在数字化时代&#xff0c;IP地址不仅是网络设备的唯一标识符&#xff0c;更承载着用户的网络身份与位置信息。百度贴吧作为广受欢迎的社交平台&#xff0c;也遵循相关规定&#xff0c;在用户个人主页等位置展示账号IP属地信息。那么&#xff0c;百度贴吧的IP属地究竟意味着什么…

基于氢氧燃料电池的分布式三相电力系统Simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于氢氧燃料电池的分布式三相电力系统Simulink建模与仿真&#xff0c;仿真输出燃料电池中氢氧元素含量变化以及生成的H2O变化情况。 2.系统仿真结果 3.核心程序与模型 版本…

Linux驱动开发(16):输入子系统–电容触摸驱动实验

有关电容触摸的基础知识内容可以参考野火STM32相关教程&#xff0c;这里只介绍电容触摸驱动的相关内容。 本章配套源码、设备树以及更新固件位于“~/embed_linux_driver_tutorial_imx6_code/linux_driver/touch_scream_GTxxx”目录下。 触摸面板通过双面胶粘在显示屏上&#…

73 mysql replication 集群的交互

前言 新建两个数据库, 分别为 192.168.220.132:3001, 192.168.220.132:3002 设置 192.168.220.132:3001 为 master, 192.168.220.132:3002 为 slave 配置文件如下 然后使用 mysqld --initialize 来初始化 data 目录, 以及相关基础数据库 这里会为 root 账户创建一个随机的…

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

文章目录 前言什么是Benchmark&#xff1f;Benchmark 简要说明Benchmark示例BenchmarkNetworkManagerMonsterMovementPlayerMovementInterestManagement性能指标 BenchmarkIdle示例BenchmarkPrediction示例BenchmarkStinkySteak示例 前言 在现代游戏开发中&#xff0c;网络功能…

反射--反射机制

目录 一 java 1.反射的引入&#xff1a; 2.反射机制 1&#xff09; 反射会生成一个类对象------类型class类型 2&#xff09;【加载阶段】class类型相当于一面镜子------透过class 反射出 真正的类的结构 3&#xff09;反射机制原理---编译阶段---加载阶段---运行阶段 2.…

【论文笔记】LongLoRA: Efficient Fine-tuning of Long-Context Large Language Models

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: LongLoRA: Efficient Fine…

LabVIEW四边形阻抗继电器

基于LabVIEW开发了四边形阻抗继电器&#xff0c;该系统主要应用于电力系统的距离保护中。四边形阻抗继电器在克服短路点过渡电阻的影响及躲避负荷阻抗方面展现出优良的特性。通过LabVIEW图形化编程环境实现的该系统&#xff0c;具备用户友好界面和简便的操作流程&#xff0c;有…

计算机网络--路由器问题

一、路由器问题 1.计算下一跳 计算机网络--根据IP地址和路由表计算下一跳-CSDN博客 2.更新路由表 计算机网络--路由表的更新-CSDN博客 3.根据题目要求给出路由表 4.路由器收到某个分组&#xff0c;解释这个分组是如何被转发的 5.转发分组之路由器的选择 二、举个例子 …

Python安装(新手详细版)

前言 第一次接触Python&#xff0c;可能是爬虫或者是信息AI开发的小朋友&#xff0c;都说Python 语言简单&#xff0c;那么多学一些总是有好处的&#xff0c;下面从一个完全不懂的Python 的小白来安装Python 等一系列工作的记录&#xff0c;并且遇到的问题也会写出&#xff0c…

2025 年前端新技术如何塑造未来开发生态?

开发领域&#xff1a;前端开发 | AI 应用 | Web3D | 元宇宙 技术栈&#xff1a;JavaScript、React、ThreeJs、WebGL、Go 经验经验&#xff1a;6 年 前端开发经验&#xff0c;专注于图形渲染和 AI 技术 开源项目&#xff1a;AI智简未来、晓智元宇宙、数字孪生引擎 大家好&#x…