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

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

相关推荐
Chen-Edward1 小时前
有了Spring为什么还有要Spring Boot?
java·spring boot·spring
陈小桔2 小时前
idea中重新加载所有maven项目失败,但maven compile成功
java·maven
小学鸡!2 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
xiaogg36782 小时前
阿里云k8s1.33部署yaml和dockerfile配置文件
java·linux·kubernetes
逆光的July2 小时前
Hikari连接池
java
微风粼粼2 小时前
eclipse 导入javaweb项目,以及配置教程(傻瓜式教学)
java·ide·eclipse
番茄Salad2 小时前
Spring Boot临时解决循环依赖注入问题
java·spring boot·spring cloud
天若有情6733 小时前
Spring MVC文件上传与下载全面详解:从原理到实战
java·spring·mvc·springmvc·javaee·multipart
祈祷苍天赐我java之术3 小时前
Redis 数据类型与使用场景
java·开发语言·前端·redis·分布式·spring·bootstrap
Olrookie4 小时前
若依前后端分离版学习笔记(二十)——实现滑块验证码(vue3)
java·前端·笔记·后端·学习·vue·ruoyi