java中下载多个文件和文件夹打压缩包下载,并自定义包中每个文件的名称

我的需求是一个可以批量下载文件或文件夹的接口,下载一个文件就正常下载,下载多个文件或单个多个文件夹都压缩成zip下载

本来想的是直接用hutool里面的ziputil工具类就行,但是我这里报错的文件都是用随机字符串命名的,直接用ZipUtil.zip方法下载下来的压缩包中文件都是原本文件的随机字符串名称

下面是我的处理方式,其中的一些工具类和压缩相关的类还是用的hutool中的,只不过没有用 ZipUtil封装好的方法

java 复制代码
@Override
    @OperLog(type = OperType.DOWNLOAD)
    public void download(List<String> ids) {
        List<WebDisk> webDiskList = this.webDiskMapper.selectList(new QueryWrapper<WebDisk>().in("id", ids));
        if (webDiskList.isEmpty()) {
            throw new RuntimeException("文件不存在,下载失败");
        }
        if (webDiskList.size() == 1 && webDiskList.get(0).isFile()) {
            WebDisk webDisk = webDiskList.get(0);
            try (FileInputStream is = new FileInputStream(this.getFullPath(webDisk));
                 ServletOutputStream os = response.getOutputStream()) {

                response.setContentType(request.getSession().getServletContext().getMimeType(webDisk.getFileSuffix())); // 获取文件的mimetype
                response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(webDisk.getOriginName(), "UTF-8"));
                IoUtil.copy(is, os);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("下载失败,系统内部错误");
            }
        } else {
            response.setContentType(request.getSession().getServletContext().getMimeType("zip")); // 获取文件的mimetype

            try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {

                response.setHeader("content-disposition", "attachment;fileName=" +
                        URLEncoder.encode(FileNameUtil.mainName(webDiskList.get(0).getOriginName()) + ".zip", "UTF-8"));

                webDiskList.forEach(webDisk -> {
                    try {
                        this.addFileToZip(webDisk, zos, "", new HashMap<>());
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                    }
                });
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

主要的方法就是下面这个 addFileToZip方法

因为上传文件的时候用随机字符串命名就是为了防止文件名称重复,所以这里打压缩包的时候给他们都设置为上传时候的原名称,但是为了防止名称重复,以名称后面累加括号加数字的方式重命名了

因为我上传的时候校验了不能上传重复名称的文件夹,所以我这里就只处理了重名的文件

java 复制代码
 private void addFileToZip(WebDisk webDisk, ZipOutputStream zos, String path, Map<String, Integer> nameCount) throws IOException {
        String filePath = this.getFullPath(webDisk);
        File file = FileUtil.file(filePath);

        String curFilePath = path + (webDisk.isFile() ? webDisk.getOriginName() : (webDisk.getOriginName() + "/"));
        ZipEntry zipEntry = new ZipEntry(curFilePath);
        try {
            zos.putNextEntry(zipEntry);
        } catch (ZipException e) {
            // 有重复名称文件
            String mainName = FileNameUtil.mainName(curFilePath);
            String extName = FileNameUtil.extName(curFilePath);
            int num = MapUtil.getInt(nameCount, curFilePath, 0) + 1;
            String newFilePath = path + mainName + "(" + num + ")" + "." + extName;

            zipEntry = new ZipEntry(newFilePath);
            zos.putNextEntry(zipEntry);

            nameCount.put(curFilePath, num);
        }


        if (file.isFile()) {
            try (FileInputStream is = new FileInputStream(file)) {
                IoUtil.copy(is, zos);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if (file.isDirectory()) {
            this.webDiskMapper.selectList(new QueryWrapper<WebDisk>().eq("pid", webDisk.getId()).eq("is_delete", 0))
                    .forEach(sub -> {
                        try {
                            this.addFileToZip(sub, zos, webDisk.getOriginName() + File.separator, nameCount);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
        }
        zos.closeEntry();
    }

需要注意的是我这里目录的层级关系已经维护到表里了,所以递归找下级的时候直接查的库

相关推荐
huangdong_6 小时前
电商平台图片URL原图转换技术深度解析:从缩略图到高清原图的完整方案
java·后端·spring
記億揺晃着的那天6 小时前
Java 调用外部 Go 程序的实践:ProcessBuilder 在生产环境中的应用
java·golang·processbuilder
JAVA面经实录9176 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
JAVA面经实录9177 小时前
操作系统面试题
java·服务器·数据库·计算机网络·面试
一杯奶茶¥8 小时前
基于springboot的失物招领管理系统带万字文档 校园失物招领管理系统 失物认领管理系统java springboot vue
java·vue.js·spring boot·java项目
不能只会打代码8 小时前
边缘视频分析平台的架构设计与性能优化——从750ms到190ms的调优之路
java·spring boot·redis·性能优化·边缘计算·物联网竞赛
小刘|8 小时前
Spring AI Alibaba 集成和风天气 API 实战
java·服务器·前端
KANGBboy8 小时前
java知识五(继承)
java·开发语言
AI人工智能+电脑小能手8 小时前
【大白话说Java面试题 第117题】【并发篇】第17题:线程有几种状态,之间如何转换?
java·开发语言·面试
DIY源码阁8 小时前
JavaSwing饮品管理系统 - MySQL版
java·数据库·mysql·eclipse