springboot 使用zip4j下载压缩包,压缩包内的数据来自oss文件管理服务器

pom引入zip4j的包

复制代码
      <zip4j.version>2.11.1</zip4j.version>
      <dependency>
        <groupId>net.lingala.zip4j</groupId>
        <artifactId>zip4j</artifactId>
        <version>${zip4j.version}</version>
      </dependency>

两种写法,一种是传统写法

复制代码
@GetMapping(value = {"/companyFileExportZip/{companyId}"})
    @ApiOperation("丰台-演出团队附件批量导出")
    public void companyFileExportZip(@PathVariable String companyId, HttpServletResponse response) {
        log.info("companyFileExportZip companyId is {}", companyId);
        // 声明需要手动关闭的流变量(提升作用域)
        ZipOutputStream zipOut = null;
        BufferedOutputStream bufferedOut = null;

        try {
            CompanyBean companyBean = performTeamService.getById(companyId);
            response.setContentType("application/zip");
            // 处理文件名中文编码(可选优化:避免文件名乱码)
            String fileName = new String((companyBean.getCompanyName() + ".zip").getBytes("UTF-8"), "ISO-8859-1");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

            List<FileBean> fileBeanList = fileService.getFileBeanByBizId(companyId);
            String domainName = obsProperties.getDomainName();

            // 初始化输出流(替代try-with-resources)
            bufferedOut = new BufferedOutputStream(response.getOutputStream());
            zipOut = new ZipOutputStream(bufferedOut);

            for (int i = 0; i < fileBeanList.size(); i++) {
                FileBean fileBean = fileBeanList.get(i);
                String fileRealName = fileBean.getFileName();
                String fileUrl = fileBean.getFileUrl();
                String objKey = fileUrl.substring(domainName.length());
                log.info("companyFileExportZip fileName is {},objKey is {}", fileRealName, objKey);

                GetObjectRequest request = new GetObjectRequest(obsProperties.getBucketName(), objKey);
                ObsObject obsObject = obsClient.getObject(request);

                ZipEntry zipEntry = new ZipEntry(fileRealName);
                zipOut.putNextEntry(zipEntry);

                // 处理单个文件的输入流(手动关闭)
                InputStream fileIn = null;
                try {
                    fileIn = obsObject.getObjectContent();
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = fileIn.read(buffer)) != -1) {
                        zipOut.write(buffer, 0, bytesRead);
                    }
                } catch (IOException e) {
                    log.error("读取OBS文件流失败,文件名:{}", fileRealName, e);
                    throw e; // 抛出异常,让外层捕获统一处理
                } finally {
                    // 手动关闭单个文件的输入流
                    if (fileIn != null) {
                        try {
                            fileIn.close();
                        } catch (IOException e) {
                            log.warn("关闭OBS文件输入流失败,文件名:{}", fileRealName, e);
                        }
                    }
                }
                zipOut.closeEntry();
            }
            zipOut.finish();
            log.info("companyFileExportZip companyId is {} success", companyId);

        } catch (IOException e) {
            log.error("文件压缩下载失败,companyId:{}", companyId, e);
            // 确保响应状态码设置生效(避免流已提交的异常)
            if (!response.isCommitted()) {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        } finally {
            // 统一关闭外层的ZipOutputStream和BufferedOutputStream
            // 关闭顺序:先关包装流(zipOut),再关底层流(bufferedOut)
            if (zipOut != null) {
                try {
                    zipOut.close();
                } catch (IOException e) {
                    log.warn("关闭ZipOutputStream失败", e);
                }
            }
            if (bufferedOut != null) {
                try {
                    bufferedOut.close();
                } catch (IOException e) {
                    log.warn("关闭BufferedOutputStream失败", e);
                }
            }
        }
    }

一种是简便写法

复制代码
 @GetMapping(value = {"/companyFileExportZip/{companyId}"})
    @ApiOperation("丰台文旅-演出团队附件批量导出")
    public void companyFileExportZip(@PathVariable String companyId,HttpServletResponse response) {
        log.info("companyFileExportZip companyId is {}",companyId);
        CompanyBean companyBean = performTeamService.getById(companyId);
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename="+companyBean.getCompanyName()+".zip");
        try {
            List<FileBean> fileBeanList = fileService.getFileBeanByBizId(companyId);
            String domainName = obsProperties.getDomainName();
            try (ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) {
                for (int i = 0 ;i < fileBeanList.size();i++) {
                    FileBean fileBean = fileBeanList.get(i);
                    String fileName = fileBean.getFileName();
                    String fileUrl = fileBean.getFileUrl();
                    String objKey = fileUrl.substring(domainName.length());
                    log.info("companyFileExportZip fileName is {},objKey is {}",fileName,objKey);

                    GetObjectRequest request = new GetObjectRequest(obsProperties.getBucketName(), objKey);
                    ObsObject obsObject = obsClient.getObject(request);

                    ZipEntry zipEntry = new ZipEntry(fileName);
                    zipOut.putNextEntry(zipEntry);

                    try (InputStream fileIn = obsObject.getObjectContent()) {
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        while ((bytesRead = fileIn.read(buffer)) != -1) {
                            zipOut.write(buffer, 0, bytesRead);
                        }
                    }
                    zipOut.closeEntry();
                }
                zipOut.finish();
            }
            log.info("companyFileExportZip companyId is {} success",companyId);
        } catch (IOException e) {
            log.error("文件压缩下载失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

两种写法,主要起别在try、catch的使用上。这两种写法,都支持下载的压缩文件中包含压缩文件的情况

相关推荐
凡人叶枫14 分钟前
Effective C++ 条款28:避免使用 handles 指向对象内部
linux·服务器·开发语言·c++·嵌入式开发
技术小结-李爽16 分钟前
【工具】Maven的下载、安装、使用
java·maven
极创信息18 分钟前
Linux挖矿病毒深度清理实战教程,从进程隐藏、Rootkit驻留到彻底根除
java·大数据·linux·运维·安全·tomcat·健康医疗
努力成为AK大王24 分钟前
并发编程的核心挑战、优化方案与核心知识点总结
java·开发语言·数据库
云烟成雨TD28 分钟前
Agent Scope Java 2.x 系列【10】技能(Skill)
java·人工智能·agent
摇滚侠32 分钟前
SpringMVC 入门到实战 DispatcherServlet 源码解读 92-95
java·后端·spring·maven·intellij-idea
键盘歌唱家1 小时前
Spring AI 入门分享:它和“直接调 API“到底差在哪
java·人工智能·spring
宸丶一2 小时前
Day 10:LangGraph - Agent 的图执行引擎
java·windows·python
hikktn2 小时前
Excel 导出 OOM 预防实战:30 万行从堆溢出到 50MB 的演进
java·excel·easyexcel
风味蘑菇干2 小时前
WTomcat服务器
java·服务器