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

相关推荐
Madison-No76 小时前
搭建项目测试环境
linux·运维·服务器·python
+VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·课程设计
泡海椒7 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
悠悠121388 小时前
微服务通信别只看性能:REST 与 gRPC 的 6 个选型判断和一次 502 故障复盘
运维·服务器
景熙55238 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
wno7049 小时前
Spring Security权限控制
java·python·spring
wno7049 小时前
Spring Boot整合Kafka
spring boot·kafka
云老大-阿里云国际站代理商9 小时前
华为云国际站服务代理商:NAT网关怎么配?多台ECS共用公网IP要注意什么
服务器·华为云·云计算
杨运交9 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring