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();
    }

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

相关推荐
蘑菇丁15 分钟前
ansible批量生产kerberos票据,并批量分发到所有其他主机脚本
java·ide·eclipse
呼啦啦啦啦啦啦啦啦1 小时前
【Redis】持久化机制
java·redis·mybatis
我想学LINUX2 小时前
【2024年华为OD机试】 (A卷,100分)- 微服务的集成测试(JavaScript&Java & Python&C/C++)
java·c语言·javascript·python·华为od·微服务·集成测试
空の鱼7 小时前
java开发,IDEA转战VSCODE配置(mac)
java·vscode
P7进阶路8 小时前
Tomcat异常日志中文乱码怎么解决
java·tomcat·firefox
小丁爱养花8 小时前
Spring MVC:HTTP 请求的参数传递2.0
java·后端·spring
CodeClimb8 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
等一场春雨8 小时前
Java设计模式 九 桥接模式 (Bridge Pattern)
java·设计模式·桥接模式
带刺的坐椅9 小时前
[Java] Solon 框架的三大核心组件之一插件扩展体系
java·ioc·solon·plugin·aop·handler
不惑_9 小时前
深度学习 · 手撕 DeepLearning4J ,用Java实现手写数字识别 (附UI效果展示)
java·深度学习·ui