首页 > 其他分享 >根据返回的多层Json来进行创建文件,达到根据阶层创建,然后压缩成压缩包进行下载

根据返回的多层Json来进行创建文件,达到根据阶层创建,然后压缩成压缩包进行下载

时间:2024-01-22 10:55:38浏览次数:33  
标签:文件 String 创建 param Json 文件夹 File new 压缩包

临时接到一个需求说让根据按照下面的这个图片的结构来打包下载指定位置下的文件到指定位置!

实现思路:
  1.把已经实现的树形结构的代码进行调用,拿到他的数据进行创建对应的文件夹
  2.因为结构下方的文件没有特别直观的数据库中的关联关系,所以还需要对于管理关系进行梳理
  3.创建好阶级文件,然后调用网上找的工具类打包成为rar压缩包,然后把路劲交给前端进行调用下载
调用数据,然后传递给创建文件方法进行实现:
/**
 * 打包佐证成果文件,压缩成为压缩包!
 *
 * @param projectId
 * @param departId
 */
@ApiOperation(value = "打包佐证成果文件", notes = "佐证与成果-打包佐证成果文件")
@RequestMapping("/exportZip")
public Result<?> exportZip(@RequestParam(name = "projectId", required = false) String projectId, @RequestParam(name = "departId", required = true) String departId) {
    // 获取树形结构
    Result<List<SelectTreeMoneyModel>> loadAllTreeRoot = this.loadAllTreeRoot(projectId, departId);
    // 下载压缩文件,将获取到的树形结构,传递到实现类进行解析跟实现
    String downloadZipFile = downloadZipFile(loadAllTreeRoot, "佐证跟成果", "/");
    return Result.ok(downloadZipFile);
}
递归的创建子集文件夹,然后调用工具类进行压缩成为压缩包文件,注:删除文件必须捋清楚然后进行使用,其实不删除也只会在指定的位置生成一份,所以我这边没有进行使用!
 /**
 * 递归的创建子集文件夹
 *
 * @param data
 * @param rootFile
 */

private void mkdirsChild(List<SelectTreeMoneyModel> data, File rootFile) {
    for (SelectTreeMoneyModel datum : data) {
        // 创建一个file实例对象,指向文件路径(存放照片的根目录)
        File childs = new File(rootFile, datum.getTitle());
        if (!childs.exists()) {
            childs.mkdirs();
        }
        // 判断如果下面还有子节点,如果有则调用自身
        if (!datum.isLeaf()) {
            mkdirsChild(datum.getChildren(), childs);
        }
        // 如果下面没有子节点,则进行判断下面是否有附件,如果有附件则进行下载到指定的文件夹内。
        List<ProjectResult> results = iProjectResultService.list(new LambdaQueryWrapper<ProjectResult>().eq(ProjectResult::getTypeId, datum.getKey()));
        if (ObjectUtils.isNotEmpty(results)) {
            for (ProjectResult result : results) {
                List<ProjectTaskContent> projectTaskContents = projectTaskContentService.list(new LambdaQueryWrapper<ProjectTaskContent>().eq(ProjectTaskContent::getResultId, result.getId()));
                for (ProjectTaskContent projectTaskContent : projectTaskContents) {
                    // 判断附件表不是空的,则进行下载文件到对应的文件夹下
                    if (ObjectUtils.isNotEmpty(projectTaskContents)) {
                        RestTemplate restTemplate = new RestTemplate();
                        // 配置文件进行读取
                        try {
                            ResponseEntity responseEntity = restTemplate.exchange(url + projectTaskContent.getFilePath(), HttpMethod.GET, null, byte[].class);
                            byte[] fileContent = (byte[]) responseEntity.getBody();
                            // 利用 File 对象,然后使用 getName() 方法获取文件名(不包括路径)。
                            File file = new File(projectTaskContent.getName());
                            String filenameWithoutPrefix = file.getName();
                            Files.write(Paths.get(childs + "\\" + filenameWithoutPrefix), fileContent);
                        } catch (IOException e) {
                            e.getMessage();
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }
}
 /**
 * 下载压缩文件
 *
 * @param data       数据集合【key:分类名称,value:照片信息集合(key:照片名称,value:照片下载路径)】
 * @param fileStr    照片存放的文件路径
 * @param zipFileStr 压缩文件的路径(加后缀名)
 */
public String downloadZipFile(Result<List<SelectTreeMoneyModel>> data, String fileStr, String zipFileStr) {
    File rootFile = null;
    String folderPath = null;
    try {
        // 遍历传递进来的数据,然后根据传入的数据进行创建文件夹
        for (SelectTreeMoneyModel selectTreeMoneyModel : data.getResult()) {
            // 创建一个file实例对象,指向文件路径(存放照片的根目录)
            zipFileStr = folderUri + selectTreeMoneyModel.getTitle();
            folderPath = selectTreeMoneyModel.getTitle();
            rootFile = new File(zipFileUri + selectTreeMoneyModel.getTitle());
            if (!rootFile.exists()) {
                // 创建新文件夹,可以多层(mkdir()创建新文件夹,只能创建一层)
                rootFile.mkdirs();
            }
            // 根据判断递归的创建文件夹,如果是false则有子集
            if (!selectTreeMoneyModel.isLeaf()) {
                mkdirsChild(selectTreeMoneyModel.getChildren(), rootFile);
            }
        }
        // 创建文件输出流(zip流对象)【实际创建了zip文件,0kb】
        FileOutputStream fos1 = new FileOutputStream(new File(zipFileStr + ".zip"));
        // 压缩法
        toZip1(rootFile, fos1, true);
        //TODO  删除文件和压缩文件,要保证每次压缩只保存一份最新的存在。 因为是删除文件,所以要慎用
        //delFolder(folderUri + folderPath);
        //delFolder(zipFileStr);
    } catch (IOException e) {
        e.printStackTrace();
    }
    // 拼接返回的压缩包地址
    String urlResult = url + folderPath + ".zip";
    return urlResult;
}

/**
 * 删除文件夹
 *
 * @param folderPath 文件夹完整绝对路径
 */
public static void delFolder(String folderPath) {
    try {
        // 删除目录下所有内容
        delAllFile(folderPath);
        File myFilePath = new File(folderPath);
        //删除空文件夹
        myFilePath.delete();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 删除指定文件夹下所有文件
 *
 * @param path 文件夹完整绝对路径
 */
public static boolean delAllFile(String path) {
    boolean bea = false;
    File file = new File(path);
    if (!file.exists()) {
        return bea;
    }
    if (!file.isDirectory()) {
        return bea;
    }
    //
    String[] tempList = file.list();
    File temp;
    if (tempList != null) {
        for (String var : tempList) {
            // separator 代替文件或文件夹路径的斜线或反斜线,防止跨平台出现错误
            if (path.endsWith(File.separator)) {
                temp = new File(path + var);
            } else {
                temp = new File(path + File.separator + var);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                //先删除文件夹里面的文件
                delAllFile(path + "/" + var);
                //再删除空文件夹
                delFolder(path + "/" + var);
                bea = true;
            }
        }
    }
    return bea;
}

/**
 * 压缩的递归方法
 *
 * @param sourceFile       源文件
 * @param zos              zip输出流
 * @param fileName         源文件的名称
 * @param keepDirStructure 是否保留原来的目录结构,true:保留目录结构;
 *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
 */
private void compress(File sourceFile, ZipOutputStream zos, String fileName, boolean keepDirStructure) throws IOException {
    byte[] buf = new byte[2 * 1024];
    // 判断是否是一个文件
    if (sourceFile.isFile()) {
        // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
        zos.putNextEntry(new ZipEntry(fileName));
        // 创建文件(即某张图片)的输入流
        try (FileInputStream in = new FileInputStream(sourceFile)) {
            int len;
            // read方法:每调用一次就从FileInputStream流中读取一个字节,并返回下一个数据字节,若已到达末尾,就返回-1。
            while ((len = in.read(buf, 0, buf.length)) != -1) {
                zos.write(buf, 0, len);
            }
            // 实际写入到了zip输出流的zip实体中,还没写到文件中【zip文件时0kb,不能打开,因为流没有关闭】
            zos.closeEntry();
        } catch (IOException e) {
            throw new IOException(e);
        }
    } else {
        // 源文件时目录
        // 获取该目录下所有文件和目录的绝对路径
        File[] listFiles = sourceFile.listFiles();
        // 空目录
        if (listFiles == null || listFiles.length == 0) {
            // 需要保留原来的文件结构时,需要对空文件夹进行处理
            if (keepDirStructure) {
                // 空文件夹的处理
                zos.putNextEntry(new ZipEntry(fileName + "/"));
                // 没有文件,不需要文件的copy
                zos.closeEntry();
            }
        } else {
            // 非空目录
            for (File file : listFiles) {
                if (keepDirStructure) {
                    // 注意:getName()仅得到最后一层的名字,不是路径,所以要加“/”,不然所有文件都跑到压缩包根目录下了
                    compress(file, zos, fileName + "/" + file.getName(), true);
                } else {
                    compress(file, zos, file.getName(), false);
                }
            }
        }
    }
}

/**
 * 压缩成ZIP 方法1:保留多级目录结构
 *
 * @param sourceFile       照片存放路径
 * @param out              压缩文件输出流
 * @param keepDirStructure 是否保留原来的目录结构,true:保留目录结构;
 *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
 */
public void toZip1(File sourceFile, OutputStream out, boolean keepDirStructure) throws IOException {
    long start = System.currentTimeMillis();
    // 创建压缩输出流,java7的新语法:Try-with-resources,会确保异常抛出或者try代码块结束时close流【该流必须实现AutoCloseable类】(若是java7之前的版本,则不会生效)
    try (ZipOutputStream zos = new ZipOutputStream(out)) {
        // 压缩
        compress(sourceFile, zos, sourceFile.getName(), keepDirStructure);
        long end = System.currentTimeMillis();
        System.out.println("压缩完成,耗时:" + (end - start) + " ms");
    } catch (IOException e) {
        throw new IOException(e);
    }
}
最后的实现结果

      总结: 主要还是要理清楚你的层级关系,
      1.然后在递归的时候一定要递归到最底层,然后根据最底层的数据查找跟附件表有关系的ID进行查找,然后将有关系的文件下载到指定的文件夹下,
      2.然后打包成为压缩包这种实现直接可以进行百度查找到适合自己的工具类,如果不是直接适用,可以进行修改工具类的方法进行适配。

标签:文件,String,创建,param,Json,文件夹,File,new,压缩包
From: https://www.cnblogs.com/Serendipitys/p/17979459

相关文章

  • java实体类转化geojson的工具类
    1.用到的技术、工具:反射+geotools2.代码实现packageorg.jeecg.modules.web.util.geoutils;importcn.hutool.core.util.ReflectUtil;importcn.hutool.core.util.StrUtil;importcn.hutool.json.JSONArray;importcn.hutool.json.JSONObject;importcn.hutool.json.JSON......
  • 50csv表格转换为json文件
     importcsvimportjson#常规csv表格转换为json文件,表头作为字典key字段。defconvert_csv_to_json(csv_file_path,json_file_path):data=[]withopen(csv_file_path,'r',encoding='utf-8-sig')ascsv_file:csv_reader=csv.DictReader(cs......
  • Java将json字符串转换为数组的方法
    Java将json字符串转换为数组的方法在Java开发中,经常会遇到将json字符串转换为数组的需求。JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,常用于前后端数据传输和存储。而Java中的JSONArray类可以用来处理json数组。下面将介绍一种常用的方法,用于将json字符串转换为......
  • 汇编-创建多模块程序
     大型源文件难于管理且汇编速度慢。可以把单个文件拆分为多个包含文件,但是,对其中任何源文件的修改仍需对所有的文件进行整体汇编。更好的方法是把一个程序划分为模块(module)(汇编单位)。每个模块可以单独汇编,因此,对一个模块源代码的修改就只需要重新汇编该模块。链接器将所......
  • 实现创建二叉树
    创建二叉树1.前序遍历创建二叉树importjava.util.Scanner;//注意类名必须为Main,不要有任何packagexxx信息classTreeNode{publicTreeNodeleft;publiccharval;publicTreeNoderight;publicTreeNode(charval){this.val=......
  • 将 .NET 8应用 以 dotnet publish 创建容器镜像并结合 Github Actions 部署到 Azure
    介绍.NET8无需DockerFile即可为.NET应用创建docker映像的新方法,我将使用dotnetpublish将.NET应用容器化,在本文中,我将分享我如何为.NET8的项目创建一个简单的ci/cd的经验。它包括2个主题:创建用于生成.NET应用并将其发布到Azure的GitHub工作流如何使用do......
  • 序列化之@JsonComponent、@JsonInclude、@JsonSerialize、@JsonIgnore、JsonProperty
    前言:很多时候,例如前端需要字段user可能只是需要用到user中的userName属性,而后端传过去的却是一整个user对象,这样显然是不行的。那有没有一种技术,可以把后端传给前端的user类型的值改变为userName类型的值呢?@JsonComponent、@JsonInclude、@JsonSerialize可以在序列化的时候动手脚,可......
  • Visual Studio Code 解决JSON中不允许注释?
    1.使用vscode打开json文件后,一些注释显示如图所示,有红色波浪线,影响阅读 2.悬浮在波浪线报错信息,会弹出提示ViewProblem,提示问题是:json文件中不允许注释 3.下面图片表示json文件中不允许注释 4.点击底部工具栏的JSON 5.弹出的窗口中输入jsonwithComments,找......
  • 金蝶云星空创建表单插件项目
     一、新建一个空的解决方案  二、新建一个类库     三、添加引用添加金蝶安装目录的引用,如果是协同开发,那就是使用工作空间下的dll。本地金蝶云安装目录:C:\ProgramFiles(x86)\Kingdee\K3Cloud\WebSite\bin协同开发工作目录:D:\WorkSpace\XXXX\mm_k3Cloud\K3......
  • .NET字符串内存管理:常量字符串、动态创建和字符串池的巧妙结合
     在.NET中,字符串是不可变的,这意味着一旦创建,字符串的内容就不能被修改。字符串在内存中以不同的方式存储,具体取决于它是常量字符串还是动态创建的字符串。常量字符串常量字符串在编译时就被解析,并在程序的元数据(Metadata)中存储。多个相同的字符串常量可能会共享同一块内存......