feat:新增文件工具箱

- 本地查找
- 文件树状图
- Diff
- 文件加密
- 批量修改文件名
- 文件格式转换
This commit is contained in:
czhqwer
2025-04-01 23:12:24 +08:00
parent eabdb649f1
commit ec6caafed9
15 changed files with 1027 additions and 47 deletions
@@ -1,42 +0,0 @@
package cn.czh.controller;
import cn.czh.base.Result;
import cn.czh.service.IFileSearchService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@RequestMapping("/fileSearch")
@RestController
public class FileSearchController {
@Resource
private IFileSearchService fileSearchService;
/**
* 获取系统磁盘列表
*/
@GetMapping("/getDrives")
public Result<?> getDrives() {
return Result.success(fileSearchService.getDrives());
}
/**
* 根据指定的磁盘列表构建文件索引
*/
@PostMapping("/buildIndex")
public Result<?> buildIndex(@RequestBody List<String> drives) {
return Result.success(fileSearchService.buildIndex(drives));
}
/**
* 根据文件名称模糊查询
*/
@GetMapping("/search")
public Result<?> search(@RequestParam String keyword) {
return Result.success(fileSearchService.searchFiles(keyword));
}
}
@@ -0,0 +1,75 @@
package cn.czh.controller;
import cn.czh.base.Result;
import cn.czh.service.ILocalFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@RequestMapping("/localFile")
@RestController
public class LocalSearchController {
@Resource
private ILocalFileService fileSearchService;
/**
* 获取系统磁盘列表
*/
@GetMapping("/getDrives")
public Result<?> getDrives() {
return Result.success(fileSearchService.getDrives());
}
/**
* 根据指定的磁盘列表构建文件索引
*/
@PostMapping("/buildIndex")
public Result<?> buildIndex(@RequestBody List<String> drives) {
return Result.success(fileSearchService.buildIndex(drives));
}
/**
* 根据文件名称模糊查询
*/
@GetMapping("/search")
public Result<?> search(@RequestParam String keyword) {
return Result.success(fileSearchService.searchFiles(keyword));
}
/**
* 根据文件地址打开目录
*/
@PostMapping("/openDir")
public Result<?> openDir(@RequestParam String dir) {
try {
Runtime.getRuntime().exec("explorer.exe /select," + dir);
return Result.success();
} catch (Exception e) {
log.error("打开目录失败:{}", e.getMessage(), e);
return Result.error("打开目录失败");
}
}
/**
* 根据文件目录展示文件树
*/
@GetMapping("/getFileTree")
public Result<?> getFileTree(
@RequestParam String path,
@RequestParam(defaultValue = "true") boolean showFiles,
@RequestParam(defaultValue = "true") boolean showFolders,
@RequestParam(defaultValue = "3") int maxDepth
) {
// 避免直接输入磁盘进去全盘扫描
if (path.length() == 2 && path.endsWith(":")) {
return Result.error("请选择目录");
}
return Result.success(fileSearchService.getFileTree(path, showFiles, showFolders, maxDepth));
}
}
@@ -0,0 +1,12 @@
package cn.czh.dto;
import lombok.Data;
import java.util.List;
@Data
public class FileNode {
private String name; // 文件/文件夹名称
private String path; // 绝对路径
private boolean isFolder; // 是否是文件夹
private List<FileNode> children; // 子节点
}
@@ -1,10 +1,11 @@
package cn.czh.service;
import cn.czh.dto.FileNode;
import cn.czh.dto.IndexResult;
import java.util.List;
public interface IFileSearchService {
public interface ILocalFileService {
List<String> getDrives();
@@ -12,4 +13,6 @@ public interface IFileSearchService {
List<String> searchFiles(String keyword);
FileNode getFileTree(String path, boolean showFiles, boolean showFolders, int maxDepth);
}
@@ -1,7 +1,8 @@
package cn.czh.service.impl;
import cn.czh.dto.FileNode;
import cn.czh.dto.IndexResult;
import cn.czh.service.IFileSearchService;
import cn.czh.service.ILocalFileService;
import cn.czh.utils.FileSearchUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -14,7 +15,7 @@ import java.util.stream.Collectors;
@Slf4j
@Service
public class FileSearchServiceImpl implements IFileSearchService {
public class LocalFileServiceImpl implements ILocalFileService {
@Resource
private FileSearchUtil fileSearchUtil;
@@ -76,4 +77,44 @@ public class FileSearchServiceImpl implements IFileSearchService {
public List<String> searchFiles(String keyword) {
return fileSearchUtil.search(keyword);
}
@Override
public FileNode getFileTree(String path, boolean showFiles, boolean showFolders, int maxDepth) {
File root = new File(path);
if (!root.exists() || !root.isDirectory()) {
return null;
}
return buildFileTree(root, showFiles, showFolders, 0, maxDepth);
}
private FileNode buildFileTree(File file, boolean showFiles, boolean showFolders, int currentDepth, int maxDepth) {
// 判断是否匹配类型
boolean matchesType = (file.isDirectory() && showFolders) || (!file.isDirectory() && showFiles);
// 如果不匹配类型则不包含此节点
if (!matchesType) {
return null;
}
FileNode node = new FileNode();
node.setName(file.getName());
node.setPath(file.getAbsolutePath());
node.setFolder(file.isDirectory());
// 如果是目录且未达到最大深度递归构建子节点
if (file.isDirectory() && (maxDepth == 0 || currentDepth < maxDepth)) {
File[] files = file.listFiles();
if (files != null) {
List<FileNode> children = new ArrayList<>();
for (File f : files) {
FileNode child = buildFileTree(f, showFiles, showFolders, currentDepth + 1, maxDepth);
if (child != null) {
children.add(child);
}
}
node.setChildren(children.isEmpty() ? null : children);
}
}
return node;
}
}