Java应用关于获取无限层级文件树TreeFileData的心得

用到了hutoollombok。@ApiOperationSupport()注解是knife4j的,聚合swagger文档的。不需要可以删了。还有一个@Api开头的swagger注解之类的,@ApiLog是aop接口日志,该删的就删,都是辅助功能,主要看代码意思就行。


1.pom文件

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>

直接贴代码了

2.Controller文件

这个主要看TreeData就好了,私有方法getFileTree使用递归,id生成不需要可以删了,

public class FileController {
	private static String rootPath = System.getProperty("user.dir");
	private static String sourcePath = rootPath + File.separator + "src";
	private static String tempPath = sourcePath + File.separator + "temp";
	// 线程间隔离对象,生成id用
	private static ThreadLocal<Integer> id = new ThreadLocal<Integer>();

	@GetMapping("/treeData")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "获取文件树数据 id生成策略为  层数+000+id")
	@ApiLog("获取文件树数据 id生成策略为  层数+000+id")
	public R<List<FileNode>> treeData() {
		FileUtil.mkdir(this.getUserPath());
		id.set(1);
		List<FileNode> fileTree = this.getFileTree(this.getUserPath(), 1);
		return R.data(fileTree);
	}
	@GetMapping("/value")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "获取单文件内容")
	@ApiLog("获取单文件内容")
	public R<String> value(@RequestParam @ApiParam(required = true) String filePath) {
		String fileValue = FileUtil.readUtf8String(filePath);
		return R.data(fileValue);
	}
	@PostMapping("/upload")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "上传文件")
	@ApiLog("上传文件")
	public R<String> upload(@RequestParam @ApiParam(required = true) String uploadPath,
							@RequestParam @ApiParam(required = true) MultipartFile file) {
		// 做校验只能上传sourcePath文件夹内
		if (StringUtil.isEmpty(uploadPath) || !uploadPath.contains(sourcePath)) {
			uploadPath = this.getUserPath();
		}
		FileUtil.mkdir(uploadPath);
		try {
			file.transferTo(Paths.get(uploadPath, file.getOriginalFilename()));
		} catch (IOException e) {
			e.printStackTrace();
			return R.fail("上传失败" + e.getMessage());
		}
		return R.success("上传成功");
	}
	@PostMapping("/download")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "下载文件")
	@ApiLog("下载文件")
	public void download(@RequestParam @ApiParam(required = true) String filePath, HttpServletResponse response) {
		File file = new File(filePath);
		response.setCharacterEncoding("UTF-8"); //设置编码字符
		response.setContentType("application/octet-stream;charset=UTF-8"); //设置下载内容类型
		response.setHeader("Content-disposition", "attachment;filename=" + file.getName());//设置下载的文件名称
		try (OutputStream out = response.getOutputStream() //创建页面返回方式为输出流,会自动弹出下载框
		) {
			FileUtil.writeToStream(file, out);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
        @PostMapping("/download/zip")
	@ApiOperationSupport(order = 14)
	@ApiOperation(value = "下载为Zip文件")
	@ApiLog("下载为Zip文件")
	public void downloadZip(@RequestParam @ApiParam(required = true) String filePath, HttpServletResponse response) {
		File zip = null;
		try (OutputStream out = response.getOutputStream() //创建页面返回方式为输出流,会自动弹出下载框
		) {
			zip = ZipUtil.zip(filePath);
			response.setCharacterEncoding("UTF-8"); //设置编码字符
			response.setContentType("application/octet-stream;charset=UTF-8"); //设置下载内容类型
			response.setHeader("Content-disposition", "attachment;filename=" + zip.getName());//设置下载的文件名称
			FileUtil.writeToStream(zip, out);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			zip.delete();
		}
	}
        @PostMapping("/save")
	@ApiOperationSupport(order = 15)
	@ApiOperation(value = "保存文件内容")
	@ApiLog("保存文件内容")
	public R<String> save(@RequestParam @ApiParam(required = true) String filePath,
						  @RequestParam @ApiParam(required = true) String value) {
		try {
			FileUtil.writeUtf8String(value, filePath);
		} catch (Exception e) {
			log.error(e.getCause().toString());
			e.printStackTrace();
			return R.fail("保存失败" + e.getMessage());
		}
		return R.success("保存成功");
	}

	@PostMapping("/del")
	@ApiOperationSupport(order = 16)
	@ApiOperation(value = "文件删除(包括文件夹)")
	@ApiLog("文件删除(包括文件夹)")
	public R<String> del(@RequestParam @ApiParam(required = true) String filePath) {
		try {
			boolean del = FileUtil.del(filePath);
			if (del == false) {
				return R.fail("删除失败");
			}
		} catch (Exception e) {
			log.error(e.getCause().toString());
			e.printStackTrace();
			return R.fail("删除失败" + e.getMessage());
		}
		return R.success("删除成功");
	}

	@PostMapping("/modify/name")
	@ApiOperationSupport(order = 17)
	@ApiOperation(value = "修改文件名(包括文件夹)")
	@ApiLog("修改文件名(包括文件夹)")
	public R<String> modifyName(@RequestParam @ApiParam(required = true) String filePath,
								@RequestParam @ApiParam(required = true) String name) {
		try {
			// isRetainExt为true时,保留扩展名
			FileUtil.rename(new File(filePath), name, true, true);
		} catch (Exception e) {
			log.error(e.getCause().toString());
			e.printStackTrace();
			return R.fail("修改失败" + e.getMessage());
		}
		return R.success("修改成功");
	}

	@PostMapping("/mkdir")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "新建文件夹")
	@ApiLog("新建文件夹")
	public R<String> mkdir(@RequestParam @ApiParam(required = true) String filePath,
						   @RequestParam @ApiParam(required = true) String name) {
		try {
			FileUtil.mkdir(String.valueOf(Paths.get(filePath, name)));
		} catch (Exception e) {
			log.error(e.getCause().toString());
			e.printStackTrace();
			return R.fail("新建文件夹失败" + e.getMessage());
		}
		return R.success("新建文件夹成功");
	}

	@PostMapping("/mkfile")
	@ApiOperationSupport(order = 18)
	@ApiOperation(value = "新建文件")
	@ApiLog("新建文件")
	public R<String> mkfile(@RequestParam @ApiParam(required = true) String filePath,
							@RequestParam @ApiParam(required = true) String name) {
		try {
			File file = FileUtil.newFile(String.valueOf(Paths.get(filePath, name)));
			boolean newFile = file.createNewFile();
			if (newFile == false) {
				return R.fail("新建文件失败");
			}
		} catch (Exception e) {
			log.error(e.getCause().toString());
			e.printStackTrace();
			return R.fail("新建文件失败" + e.getMessage());
		}
		return R.success("新建文件成功");
	}

	/**
	 * 递归获取无限层级文件树
	 * id生成策略为  层数+000+id
	 *
	 * @param filePath
	 * @param level
	 * @return
	 */
	private List<FileNode> getFileTree(String filePath, int level) {
		List<FileNode> list = new ArrayList<>();
		for (File file : FileUtil.ls(filePath)) {
			FileNode fileNode = new FileNode();
			int tempId = Integer.valueOf(level + "000" + id.get());
			fileNode.setId(tempId);
			fileNode.setLevel(level);
			fileNode.setName(file.getName());
			fileNode.setPath(file.getPath());
			fileNode.setType(file.isDirectory() ? 0 : 1);
			id.set(id.get() + 1);
			if (file.isDirectory()) {
				fileNode.setChild(this.getFileTree(file.getPath(), level + 1));
			} else {
				fileNode.setChild(null);
			}
			list.add(fileNode);
		}
		return list;
	}
        private String getUserPath() {
		try {
			// User user = AuthUtil.getUser();
			//String userName = user.getUserName();
			return Paths.get(tempPath, "user").toString();
		} catch (Exception e) {
			return tempPath;
		}
	}
}

3.封装返回类

@ApiModel(
    description = "返回信息"
)
public class R<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(
        value = "状态码",
        required = true
    )
    private int code;
    @ApiModelProperty(
        value = "是否成功",
        required = true
    )
    private boolean success;
    @ApiModelProperty("承载数据")
    private T data;
    @ApiModelProperty(
        value = "返回消息",
        required = true
    )
    private String msg;

    private R(IResultCode resultCode) {
        this(resultCode, (Object)null, resultCode.getMessage());
    }

    private R(IResultCode resultCode, String msg) {
        this(resultCode, (Object)null, msg);
    }

    private R(IResultCode resultCode, T data) {
        this(resultCode, data, resultCode.getMessage());
    }

    private R(IResultCode resultCode, T data, String msg) {
        this(resultCode.getCode(), data, msg);
    }

    private R(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.success = ResultCode.SUCCESS.code == code;
    }

    public static boolean isSuccess(@Nullable R<?> result) {
        return (Boolean)Optional.ofNullable(result).map((x) -> {
            return ObjectUtil.nullSafeEquals(ResultCode.SUCCESS.code, x.code);
        }).orElse(Boolean.FALSE);
    }

    public static boolean isNotSuccess(@Nullable R<?> result) {
        return !isSuccess(result);
    }

    public static <T> R<T> data(T data) {
        return data(data, "操作成功");
    }

    public static <T> R<T> data(T data, String msg) {
        return data(200, data, msg);
    }

    public static <T> R<T> data(int code, T data, String msg) {
        return new R(code, data, data == null ? "暂无承载数据" : msg);
    }

    public static <T> R<T> success(String msg) {
        return new R(ResultCode.SUCCESS, msg);
    }

    public static <T> R<T> success(IResultCode resultCode) {
        return new R(resultCode);
    }

    public static <T> R<T> success(IResultCode resultCode, String msg) {
        return new R(resultCode, msg);
    }

    public static <T> R<T> fail(String msg) {
        return new R(ResultCode.FAILURE, msg);
    }

    public static <T> R<T> fail(int code, String msg) {
        return new R(code, (Object)null, msg);
    }

    public static <T> R<T> fail(IResultCode resultCode) {
        return new R(resultCode);
    }

    public static <T> R<T> fail(IResultCode resultCode, String msg) {
        return new R(resultCode, msg);
    }

    public static <T> R<T> status(boolean flag) {
        return flag ? success("操作成功") : fail("操作失败");
    }

    public int getCode() {
        return this.code;
    }

    public boolean isSuccess() {
        return this.success;
    }

    public T getData() {
        return this.data;
    }

    public String getMsg() {
        return this.msg;
    }

    public void setCode(final int code) {
        this.code = code;
    }

    public void setSuccess(final boolean success) {
        this.success = success;
    }

    public void setData(final T data) {
        this.data = data;
    }

    public void setMsg(final String msg) {
        this.msg = msg;
    }

    public String toString() {
        return "R(code=" + this.getCode() + ", success=" + this.isSuccess() + ", data=" + this.getData() + ", msg=" + this.getMsg() + ")";
    }

    public R() {
    }
}

4.返回文件节点

@Data
public class FileNode {
	@ApiModelProperty(value = "id")
	private Integer id;

	@ApiModelProperty(value = "文件树层级")
	private Integer level;

	@ApiModelProperty(value = "文件名")
	private String name;

	@ApiModelProperty(value = "文件相对路径")
	private String path;

	@ApiModelProperty(value = "类型 0文件夹 1文件")
	private Integer type;

	@ApiModelProperty(value = "文件树子节点")
	private List<FileNode> child;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值