用到了hutool,lombok。@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;
}