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的使用上。这两种写法,都支持下载的压缩文件中包含压缩文件的情况

相关推荐
小辰记事本4 小时前
从零读懂RoCEv2数据包构造:从WQE到线缆上的完整旅程
服务器·网络·网络协议·rdma
Mahir085 小时前
Spring 循环依赖深度解密:从问题本质到三级缓存源码级解析
java·后端·spring·缓存·面试·循环依赖·三级缓存
RyFit6 小时前
SpringAI 常见问题及解决方案大全
java·ai
石山代码6 小时前
C++ 内存分区 堆区
java·开发语言·c++
绝知此事6 小时前
【算法突围 01】线性结构与哈希表:后端开发的收纳术
java·数据结构·算法·面试·jdk·散列表
无风听海6 小时前
C# 隐式转换深度解析
java·开发语言·c#
一只大袋鼠7 小时前
Git 进阶(二):分支管理、暂存栈、远程仓库与多人协作
java·开发语言·git
江公望8 小时前
Ubuntu htop命令,10分钟讲清楚
linux·服务器
哎呦,帅小伙哦8 小时前
Linux 时间:从原子钟到 clock_gettime 的每一面
linux·运维·服务器
德思特8 小时前
从 Dify 配置页理解 RAG 的重要参数
java·人工智能·llm·dify·rag