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

相关推荐
2601_962189603 小时前
【SpringBoot】使用IDEA创建SpringBoot项目
java·spring boot·intellij-idea
步行cgn3 小时前
Spring Boot 启动报错:MissingServletWebServerFactoryBean 的排查与解决
java·spring boot·后端
XLYcmy3 小时前
HTML/CSS/JS 基础与 Vue 技术栈深度解析
java·前端·css·html·vue3·vue2·api
~木雨4 小时前
String 底层原理与常量池全解析:byte []+coder、intern 陷阱、substring 内存泄漏,一篇讲透
java·jvm·内存优化·string·字符串常量池
新知图书4 小时前
12.3 智能体中Skill的约束与自进化实战
java·前端·数据库
Alphapeople4 小时前
moveit真机部署
linux·运维·服务器
en.en..4 小时前
C语言 static函数与头文件封装规范
java·c语言·前端
步行cgn4 小时前
Spring Boot 项目打包部署详解
java·spring boot·后端
pnoker4 小时前
拆解 IoT DC3:六层微服务架构
java·物联网·spring cloud·微服务·架构
cfm_29144 小时前
ThreadLocal 内存泄漏
java·jvm