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

实现思路:
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.然后打包成为压缩包这种实现直接可以进行百度查找到适合自己的工具类,如果不是直接适用,可以进行修改工具类的方法进行适配。

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

  1. java使用io创建文件与删除文件的工具类

    java中对于文件的操作,是再常见不过了.以下代码是自己代码中所用到的工具类,仅供参考. import java.io.File; import java.io.IOException; /** * ...

  2. JAVA之旅(二十八)——File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤

    JAVA之旅(二十八)--File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤 我们可以继续了,今天说下File 一.File概述 文件的操作是非常 ...

  3. JAVA 创建文件和文件夹,删除文件和文件夹的实用工具

    package com.file; import java.io.File; import java.io.IOException; //创建新文件和目录 public class CCRDFile ...

  4. JAVA 创建文件和文件夹,删除文件和文件夹的实用工具

    package com.file; import java.io.File; import java.io.IOException; //创建新文件和目录 public class CCRDFile ...

  5. 总结java创建文件夹的4种方法及其优缺点-JAVA IO基础总结第三篇

    本文是Java IO总结系列篇的第3篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...

  6. Linux 删除文件夹和创建文件的命令

    删除文件夹实例:rm -rf /var/log/httpd/access将会删除/var/log/httpd/access目录以及其下所有文件.文件夹 删除文件使用实例: rm -f /var/log ...

  7. c# ftp创建文件(非上传文件)

    c#  ftp创建文件(非上传文件) 一.奇葩的故事: 今天项目中遇到这么个奇葩的问题,ftp文件传输完成后要在ftp目录下另一个文件夹下创建对应的空文件,听说是为了文件的完整性,既然这么说,那么就必 ...

  8. Ubuntu上使用过的命令,Linux常用命令,mount 硬盘挂载, ls 列表list命令,cp 复制copy命令,mkdir 创建文件夹 ,nano 编辑器,cat 文档合并,chmod 文件权限,ssh win10连接ubuntu服务器的步骤

    man 帮助 > man ls # ubuntu的帮助 tar.gz 压缩解压 > tar -zcvf yzn.tar.gz /home/yzn # 压缩 > tar -zxvf y ...

  9. 返回值是JSON的阿贾克斯方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. [原创作品] 对获取多层json值的封装

    今天篇头不废话了,交流加群:164858883 在我们接收后端返回的json数据的时候,在数据缺失的时候,如果直接接收会导致致命错误的发生.可能有些同学会说通常都会有,不用判断直接获取也行.之前我也是 ...

随机推荐

  1. 【2016】CloneCD和IsoBuster配合使用以提取VCD中的文件

    **笔记记录于:2016-11-24 ** 本文章仅供用于技术研究用途,请勿利用文章内容操作用于违反法律的事情. 起因: 公司老总让我提取下VCD中的文件以备份下,但是把光碟放进DVD光驱中发现只有几 ...

  2. Semantic Kernel 正式发布 v1.0.1 版本

    微软在2023年12月19日在博客上(Say hello to Semantic Kernel V1.0.1)发布了Semantic kernel的.NET 正式1.0.1版本.新版本提供了新的文档, ...

  3. ElasticSearch之cat health API

    命令样例如下: curl -X GET "https://localhost:9200/_cat/health?v=true&pretty" --cacert $ES_HO ...

  4. CVE-2016-5734 复现

    CVE-2016-5734 漏洞简介 phpMyAdmin 4.0.x-4.6.2 远程代码执行漏洞(CVE-2016-5734) phpMyAdmin是一套开源的.基于Web的MySQL数据库管理工 ...

  5. Ubuntu图形界面root登录“sorry, that didn't work please

    https://blog.51cto.com/u_14757092/2484490 ssh登录主机执行下vim /etc/pam.d/gdm-autologin 注释行 "auth requ ...

  6. Project Based Learning 基于项目的编程学习

    Project Based Learning https://github.com/practical-tutorials/project-based-learning.git A list of p ...

  7. ElasticSearch-1

    原文链接:https://gaoyubo.cn/blogs/52ef5bf7.html 一.Elasticsearch 架构设计 Elasticsearch 架构层: Elasticsearch 五层 ...

  8. Java 将PPT转为OFD

    本文以Java后端程序代码展示如何实现将PPT幻灯片转成OFD格式.下面是具体步骤. 步骤1:安装PPT库-Spire.Presentation for Java 方法一.通过Maven仓库安装.在p ...

  9. 抖音上超好听的神曲音乐,Python教你一次性下载

    不知道什么时候开始,中国出现了南抖音.北快手的互文格局(东市买骏马,西市买鞍鞯-).刚才提到了,之前比较喜欢刷抖音,对于我这种佛系程序猿,看网上这些整容妹子基本一个样.喜欢抖音主要是两个初衷,学做菜听 ...

  10. 一文带你了解EiPaaS和EiPaaS的国际趋势

    摘要:EiPaaS (Enterprise Integration Platform as a Service) 是企业级的集成平台和服务. 本文分享自华为云社区<初识EiPaaS和EiPaaS ...