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

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

相关推荐
天天扭码13 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶13 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺18 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序25 分钟前
vue3 封装request请求
java·前端·typescript·vue
陈王卜43 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、43 分钟前
Spring Boot 注解
java·spring boot
java亮小白19971 小时前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF1 小时前
java Queue 详解
java·队列
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql