commit 32ed3114d4753cf837fcf1c95e6ad177780565c4
Author: liwenxuan <1298531568@qq.com>
Date: Wed Dec 24 13:07:45 2025 +0800
首次提交
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5cb0c93
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,132 @@
+# ===========================================
+# 编译和构建输出
+# ===========================================
+target/
+build/
+out/
+bin/
+*.class
+*.jar
+*.war
+*.ear
+
+# ===========================================
+# 依赖和缓存
+# ===========================================
+.m2/repository/
+.gradle/
+node_modules/
+
+# ===========================================
+# 日志文件
+# ===========================================
+*.log
+logs/
+log/
+
+# ===========================================
+# 配置文件(包含敏感信息)
+# ===========================================
+# 主要配置文件
+application.properties
+application.yml
+application-*.properties
+application-*.yml
+
+# 例外:可以提交示例配置文件
+!application.properties.example
+!application.yml.example
+
+# ===========================================
+# IDE 配置文件
+# ===========================================
+# IntelliJ IDEA
+.idea/
+*.iws
+*.iml
+*.ipr
+*.eml
+.idea_modules/
+
+# Eclipse
+.settings/
+.project
+.classpath
+.metadata/
+
+# NetBeans
+nbproject/
+nbactions.xml
+
+# VS Code
+.vscode/
+!.vscode/settings.json.example
+!.vscode/launch.json.example
+
+# ===========================================
+# 操作系统文件
+# ===========================================
+# Windows
+Thumbs.db
+ehthumbs.db
+Desktop.ini
+
+# Mac OS X
+.DS_Store
+
+# Linux
+*~
+
+# ===========================================
+# 临时文件
+# ===========================================
+*.tmp
+*.temp
+*~
+~*
+*.swp
+*.swo
+*.#
+
+# ===========================================
+# 测试和报告
+# ===========================================
+target/surefire-reports/
+target/failsafe-reports/
+target/site/
+*.coverage
+*.coverage.xml
+
+# ===========================================
+# 上传和下载目录
+# ===========================================
+uploads/
+downloads/
+temp/
+
+# ===========================================
+# Tomcat 相关
+# ===========================================
+apache-tomcat-*/
+tomcat/
+
+# ===========================================
+# 数据库文件
+# ===========================================
+*.db
+*.sql
+*.h2.db
+
+# ===========================================
+# 文档生成
+# ===========================================
+apidocs/
+docs/_build/
+
+# ===========================================
+# 其他
+# ===========================================
+*.bak
+*.backup
+*.orig
+*.rej
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..29ffa5c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,106 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.18
+
+
+ com.example
+ file-search-service
+ 1.0.0
+ war
+ File Search Service
+ Windows Server文件搜索服务
+
+
+ 1.8
+ 1.8
+ 1.8
+ UTF-8
+ UTF-8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ file-search-service
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/example/fileservice/FileServiceApplication.java b/src/main/java/com/example/fileservice/FileServiceApplication.java
new file mode 100644
index 0000000..f1e799b
--- /dev/null
+++ b/src/main/java/com/example/fileservice/FileServiceApplication.java
@@ -0,0 +1,19 @@
+package com.example.fileservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+@SpringBootApplication
+public class FileServiceApplication extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(FileServiceApplication.class);
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(FileServiceApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/fileservice/controller/FileController.java b/src/main/java/com/example/fileservice/controller/FileController.java
new file mode 100644
index 0000000..380d440
--- /dev/null
+++ b/src/main/java/com/example/fileservice/controller/FileController.java
@@ -0,0 +1,687 @@
+package com.example.fileservice.controller;
+
+import com.example.fileservice.dto.ApiResponse;
+import com.example.fileservice.dto.FileInfo;
+import com.example.fileservice.service.FileService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource; // 正确的Spring Resource
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/files")
+@CrossOrigin(origins = "*")
+public class FileController {
+
+ @Autowired
+ private FileService fileService;
+
+ /**
+ * 查找文件(简单接口)
+ * GET /api/files/find?path=C:\Users&fileName=*.txt
+ */
+ @GetMapping("/find")
+ public ResponseEntity>> findFiles(
+ @RequestParam("path") String searchPath,
+ @RequestParam("fileName") String fileName) {
+
+ try {
+ List foundFiles = fileService.findFiles(searchPath, fileName);
+
+ if (foundFiles.isEmpty()) {
+ return ResponseEntity.ok(ApiResponse.success("未找到匹配的文件", foundFiles));
+ }
+
+ return ResponseEntity.ok(ApiResponse.success(
+ String.format("找到 %d 个文件", foundFiles.size()),
+ foundFiles
+ ));
+
+ } catch (Exception e) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error(e.getMessage()));
+ }
+ }
+
+ /**
+ * 查找文件(详细接口)
+ * GET /api/files/find-detail?path=C:\Users&fileName=*.txt&maxDepth=3
+ */
+ @GetMapping("/find-detail")
+ public ResponseEntity>> findFilesWithDetail(
+ @RequestParam("path") String searchPath,
+ @RequestParam("fileName") String fileName,
+ @RequestParam(value = "maxDepth", defaultValue = "5") int maxDepth) {
+
+ try {
+ // 限制最大深度,防止递归过深
+ if (maxDepth < 1 || maxDepth > 20) {
+ maxDepth = 5;
+ }
+
+ // 方法1: 使用 findFilesWithInfo 方法(如果存在)
+ // List foundFiles = fileService.findFilesWithInfo(searchPath, fileName);
+
+ // 方法2: 使用 findFiles 获取路径,然后转换为 FileInfo
+ List foundFiles = fileService.findFiles(searchPath, fileName, maxDepth)
+ .stream()
+ .map(path -> fileService.getFileInfo(path))
+ .collect(Collectors.toList());
+
+ return ResponseEntity.ok(ApiResponse.success(
+ String.format("找到 %d 个文件", foundFiles.size()),
+ foundFiles
+ ));
+
+ } catch (Exception e) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error(e.getMessage()));
+ }
+ }
+
+ /**
+ * 获取文件信息
+ * GET /api/files/info?path=C:\Windows\notepad.exe
+ */
+ @GetMapping("/info")
+ public ResponseEntity> getFileInfo(
+ @RequestParam("path") String filePath) {
+
+ try {
+ FileInfo fileInfo = fileService.getFileInfo(filePath);
+ return ResponseEntity.ok(ApiResponse.success(fileInfo));
+
+ } catch (Exception e) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error(e.getMessage()));
+ }
+ }
+
+ /**
+ * 列出目录内容
+ * GET /api/files/list?path=C:\Windows
+ */
+ @GetMapping("/list")
+ public ResponseEntity>> listDirectory(
+ @RequestParam("path") String dirPath) {
+
+ try {
+ List fileList = fileService.listDirectory(dirPath);
+ return ResponseEntity.ok(ApiResponse.success(
+ String.format("目录包含 %d 个项目", fileList.size()),
+ fileList
+ ));
+
+ } catch (Exception e) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error(e.getMessage()));
+ }
+ }
+
+ /**
+ * 获取目录统计信息
+ * GET /api/files/stats?path=C:\Windows
+ */
+ @GetMapping("/stats")
+ public ResponseEntity> getDirectoryStats(
+ @RequestParam("path") String dirPath) {
+
+ try {
+ FileService.DirectoryStats stats = fileService.getDirectoryStats(dirPath);
+ return ResponseEntity.ok(ApiResponse.success(stats));
+
+ } catch (Exception e) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error(e.getMessage()));
+ }
+ }
+
+ /**
+ * 批量查找文件(POST请求)
+ * POST /api/files/batch-find
+ */
+ @PostMapping("/batch-find")
+ public ResponseEntity>> batchFindFiles(
+ @Valid @RequestBody FileSearchRequest request) {
+
+ try {
+ // 验证参数
+ if (request.getSearchPath() == null || request.getSearchPath().isEmpty()) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error("搜索路径不能为空"));
+ }
+
+ if (request.getFileName() == null || request.getFileName().isEmpty()) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error("文件名不能为空"));
+ }
+
+ // 限制最大深度
+ int maxDepth = request.getMaxDepth();
+ if (maxDepth < 1 || maxDepth > 10) {
+ maxDepth = 5;
+ }
+
+ List foundFiles = fileService.findFiles(
+ request.getSearchPath(),
+ request.getFileName(),
+ maxDepth
+ ).stream()
+ .map(path -> fileService.getFileInfo(path))
+ .collect(Collectors.toList());
+
+ // 如果指定了最大结果数,则截取结果
+ if (request.getMaxResults() > 0 && foundFiles.size() > request.getMaxResults()) {
+ foundFiles = foundFiles.subList(0, request.getMaxResults());
+ }
+
+ return ResponseEntity.ok(ApiResponse.success(
+ String.format("找到 %d 个文件,显示前 %d 个",
+ foundFiles.size(),
+ Math.min(foundFiles.size(), request.getMaxResults() > 0 ? request.getMaxResults() : foundFiles.size())),
+ foundFiles
+ ));
+
+ } catch (Exception e) {
+ return ResponseEntity.badRequest()
+ .body(ApiResponse.error(e.getMessage()));
+ }
+ }
+
+ /**
+ * 文件搜索请求类
+ */
+ public static class FileSearchRequest {
+ @NotBlank(message = "搜索路径不能为空")
+ private String searchPath;
+
+ @NotBlank(message = "文件名不能为空")
+ private String fileName;
+
+ private int maxDepth = 5;
+ private int maxResults = 100;
+ private boolean includeHidden = false;
+ private long minSize = 0;
+ private long maxSize = Long.MAX_VALUE;
+
+ // Getter和Setter
+ public String getSearchPath() {
+ return searchPath;
+ }
+
+ public void setSearchPath(String searchPath) {
+ this.searchPath = searchPath;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public int getMaxDepth() {
+ return maxDepth;
+ }
+
+ public void setMaxDepth(int maxDepth) {
+ this.maxDepth = maxDepth;
+ }
+
+ public int getMaxResults() {
+ return maxResults;
+ }
+
+ public void setMaxResults(int maxResults) {
+ this.maxResults = maxResults;
+ }
+
+ public boolean isIncludeHidden() {
+ return includeHidden;
+ }
+
+ public void setIncludeHidden(boolean includeHidden) {
+ this.includeHidden = includeHidden;
+ }
+
+ public long getMinSize() {
+ return minSize;
+ }
+
+ public void setMinSize(long minSize) {
+ this.minSize = minSize;
+ }
+
+ public long getMaxSize() {
+ return maxSize;
+ }
+
+ public void setMaxSize(long maxSize) {
+ this.maxSize = maxSize;
+ }
+
+ @Override
+ public String toString() {
+ return "FileSearchRequest{" +
+ "searchPath='" + searchPath + '\'' +
+ ", fileName='" + fileName + '\'' +
+ ", maxDepth=" + maxDepth +
+ ", maxResults=" + maxResults +
+ ", includeHidden=" + includeHidden +
+ ", minSize=" + minSize +
+ ", maxSize=" + maxSize +
+ '}';
+ }
+ }
+
+ /**
+ * 系统信息接口
+ * GET /api/files/system-info
+ */
+ @GetMapping("/system-info")
+ public ResponseEntity>> getSystemInfo() {
+ try {
+ Map info = new java.util.HashMap<>();
+
+ // 系统信息
+ info.put("os.name", System.getProperty("os.name"));
+ info.put("os.version", System.getProperty("os.version"));
+ info.put("os.arch", System.getProperty("os.arch"));
+ info.put("java.version", System.getProperty("java.version"));
+ info.put("java.home", System.getProperty("java.home"));
+
+ // 磁盘信息
+ java.io.File[] roots = java.io.File.listRoots();
+ List