当前位置: 首页 > article >正文

使用ZipOutputStream压缩文件、文件夹,最后输出

①使用Spring,文件在线URL输出到请求响应response,提供下载

ZipOutputStream实现了一个输出流过滤器,用于以ZIP文件格式写入文件。包括对压缩项和未压缩项的支持。

用到的方法:

putNextEntry(ZipEntry entry);

传ZipEntry类,相当于在压缩包中放了一个文件,文件内容为空

ZipEntry有一个构造器,可以实现以路径的形式生成文件夹,例如new ZipEntry("a/b/c.jpg"),最终生成的压缩包中包含a文件夹,a文件夹内部包含b,b文件夹内部包含c.jpg,利用这个性质,就可以写一个递归,检索文件夹,如果检索过程中又发现文件夹,则继续递归。

假设一个实体CloudFile

public class CloudFile {
    private String fileName;//文件名称
    private String fileUrl;//文件的url,一个在线的路径
    private String filePath;//路径
}

下面基于在线的URL文件实现,提供思路:

public void downloadDir(List<CloudFile> fileList, HttpServletResponse response) {
    ZipOutputStream zos = null;//最终输出的一个zip
    try {
        zos = new ZipOutputStream(response.getOutputStream());
        downloadDir(zos, fileList, "");//递归下载,初始父路径为空
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        try {
            if (zos != null) {
                zos.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

private void downloadDir(ZipOutputStream zos, List<CloudFile> fileList, String parentPath) {
    try {
        for (CloudFile file : fileList) {
            //当前文件的路径
            String nextPath = parentPath + "/" + file.getFileName();
            if (nextPath.charAt(0) == '/') {
                //避免文件夹以/开头
                nextPath = nextPath.substring(1);
            }
            if (file.getDirFlag().equals(DirEnum.DIR.getCode())) {
                List<CloudFile> nextList = baseMapper.selectList(Wrappers.<CloudFile>lambdaQuery()
                        .likeRight(CloudFile::getFilePath, file.getFilePath() + "/" + file.getFileName()));//类似查这个文件夹下的所有数据
                downloadDir(zos, nextList, nextPath);//继续下载文件夹
                continue;
            }
            zos.putNextEntry(new ZipEntry(nextPath));//放入当前下载的文件名称
            zos.write(IOUtils.toByteArray(new URI(file.getFileUrl()).toURL()));//从URL中写入流 commons-io
            zos.flush();
            zos.closeEntry();
        }
    } catch (IOException | URISyntaxException e) {
        throw new RuntimeException(e);
    }
}

第一次调用先查出要下载的目录fileList

调用downloadDir(fileList, response)即可(无论是文件还是文件夹,这个方法都通用)

List<CloudFile> list = cloudFileService.list(
        Wrappers.<CloudFile>lambdaQuery().eq(CloudFile::getUserId, SecurityUtil.getUserId())
        .likeRight(CloudFile::getFilePath, tmp)
);
downloadDir(list, response);

②使用本地文件夹,压缩成zip输出到相应目录

以上是从URL中提取并且下载,如果是本地File文件呢???

假设要下载这样路径的一个文件夹

—ovo-test

——aaa.txt 文件

——ovo-test2 文件夹

———bbb.txt 文件

类似上面说到的方式

public static void downloadDir(File file) {
    File outFile = new File("test.zip");//输出的zip
    ZipOutputStream zos = null;
    try {
        zos = new ZipOutputStream(new FileOutputStream(outFile));
        downloadDir(zos, file, "");
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    } finally {
        try {
            zos.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

private static void downloadDir(ZipOutputStream zos, File file, String parentPath) {
    try {
        for (File childrenFile : file.listFiles()) {
            String nextPath = parentPath + "/" + childrenFile.getName();
            if (nextPath.charAt(0) == '/') {
                nextPath = nextPath.substring(1);
            }
            if (childrenFile.isDirectory()) {
                downloadDir(zos, childrenFile, nextPath);
                return;
            }
            zos.putNextEntry(new ZipEntry(nextPath));
            zos.write(childrenFile.getAbsolutePath().getBytes(StandardCharsets.UTF_8));
            // zos.write(IOUtils.toByteArray(new FileInputStream(childrenFile))) 或者这样,用commons-io
            zos.flush();
            zos.closeEntry();
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public static void main(String[] args) {
    File file = new File("D:\\ovo-test");
    downloadDir(file);
}

执行main函数即可看到对应文件下的输出结果


http://www.kler.cn/a/374536.html

相关文章:

  • 【MySQL】 运维篇—安全管理:防止SQL注入与其他安全威胁
  • 深度学习基础—循环神经网络(RNN)
  • 移远通信闪耀2024香港秋灯展,以丰富的Matter产品及方案推动智能家居产业发展
  • Python飞舞蝙蝠
  • 在 .NET 8 Web API 中实现 Entity Framework 的 Code First 方法
  • 探索开源语音识别的未来:高效利用先进的自动语音识别技术20241030
  • 高职健康管理专业校内实训基地建设方案
  • 除了wordpress CMS外,还有什么CMS值得我们使用?
  • java开发如何在单例模式下通过锁机制防止并发?
  • QT:子线程更新UI
  • 硅谷(12)菜单管理
  • 批量图片转PDF文件的多种方法详解
  • 哈尔滨三级等保信息安全风险管理指南
  • 超详细的MySQL存储引擎讲解,学习MySQL这些知识你必须要会!
  • kan代码阅读
  • 账户和组管理
  • 若依框架部署到服务器刷新或者是退出登录出现404
  • Spring Boot2.x教程:(十)从Field injection is not recommended谈谈依赖注入
  • PVE修改Ubuntu虚拟机的硬盘大小
  • nginx 根路径同时代理 http ws sse 三种请求
  • WebGL 快速入门构建你的第一个 3D 应用
  • 在浏览器中运行 Puppeteer:解锁新能力
  • USB接口类型及引脚信号详解
  • java 实现对 word 文档中占位符进行替换
  • Spring学习笔记_13——@Autowired
  • 内网穿透技术选型PPTP(点对点隧道协议)和 FRP(Fast Reverse Proxy)