Files
klp-oa/klp-wms/src/main/java/com/klp/controller/WmsFileManagementController.java
Joshi d1255c0312 feat(file-management): 添加文件管理功能并支持环境配置
- 在 application.yml 和环境特定的配置文件中添加文件存储目录路径配置
- 新增 Stage 环境配置文件和相关设置
- 修改 WmsFileManagementController 以使用配置文件中的目录路径
- 优化文件管理相关 API 的错误处理和路径获取方式
2025-08-04 13:11:14 +08:00

378 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.klp.controller;
import com.klp.domain.FileDetailInfo;
import com.klp.domain.FileInfo;
import com.klp.domain.vo.ApiResponseVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import java.io.*;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* WMS文件管理控制器
* 提供文件读取、删除和定时删除功能
*/
@Controller
@RequestMapping("/wms/file")
public class WmsFileManagementController {
// 文件目录路径 - 从配置文件读取
@Value("${klp.file.directory-path}")
private String directoryPath;
/**
* 获取目录下所有文件基本信息(不包含文件内容)
* GET /wms/file/list
*/
@GetMapping("/list")
@ResponseBody
public ResponseEntity<ApiResponseVo<List<FileInfo>>> getAllFiles() {
try {
Path directory = Paths.get(directoryPath);
// 检查目录是否存在
if (!Files.exists(directory)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "目录不存在: " + directoryPath, null));
}
// 获取所有文件基本信息(不读取文件内容)
List<FileInfo> fileList = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path file : stream) {
if (Files.isRegularFile(file)) {
FileInfo fileInfo = readFileBasicInfo(file);
fileList.add(fileInfo);
}
}
}
String message = String.format("成功获取 %d 个文件", fileList.size());
return ResponseEntity.ok(new ApiResponseVo<>(true, message, fileList));
} catch (Exception e) {
String errorMsg = "获取文件列表失败: " + e.getMessage();
System.err.println(errorMsg);
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponseVo<>(false, errorMsg, null));
}
}
/**
* 获取单个文件的详细信息(包含文件内容)
* GET /wms/file/content/{fileName}
*/
@GetMapping("/content/{fileName}")
@ResponseBody
public ResponseEntity<ApiResponseVo<FileDetailInfo>> getFileContent(@PathVariable String fileName) {
try {
Path filePath = Paths.get(directoryPath, fileName);
// 检查文件是否存在
if (!Files.exists(filePath)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "文件不存在: " + fileName, null));
}
// 检查是否为普通文件
if (!Files.isRegularFile(filePath)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "不是普通文件: " + fileName, null));
}
// 读取文件详细信息(包含内容)
FileDetailInfo fileDetailInfo = readFileDetailInfo(filePath);
String message = "成功获取文件内容: " + fileName;
return ResponseEntity.ok(new ApiResponseVo<>(true, message, fileDetailInfo));
} catch (Exception e) {
String errorMsg = "获取文件内容失败: " + e.getMessage();
System.err.println(errorMsg);
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponseVo<>(false, errorMsg, null));
}
}
/**
* 根据文件名删除文件
* DELETE /wms/file/delete/{fileName}
*/
@DeleteMapping("/delete/{fileName}")
@ResponseBody
public ResponseEntity<ApiResponseVo<String>> deleteFile(@PathVariable String fileName) {
try {
Path filePath = Paths.get(directoryPath, fileName);
// 检查文件是否存在
if (!Files.exists(filePath)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "文件不存在: " + fileName, null));
}
// 检查是否为普通文件
if (!Files.isRegularFile(filePath)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "不是普通文件: " + fileName, null));
}
// 删除文件
Files.delete(filePath);
String message = "文件删除成功: " + fileName;
return ResponseEntity.ok(new ApiResponseVo<>(true, message, fileName));
} catch (Exception e) {
String errorMsg = "删除文件失败: " + e.getMessage();
System.err.println(errorMsg);
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponseVo<>(false, errorMsg, null));
}
}
/**
* 批量删除文件
* POST /wms/file/batch-delete
*/
@PostMapping("/batch-delete")
@ResponseBody
public ResponseEntity<ApiResponseVo<Map<String, Object>>> batchDeleteFiles(@RequestBody List<String> fileNames) {
try {
Map<String, Object> result = new HashMap<>();
List<String> successList = new ArrayList<>();
List<String> failedList = new ArrayList<>();
for (String fileName : fileNames) {
try {
Path filePath = Paths.get(directoryPath, fileName);
if (Files.exists(filePath) && Files.isRegularFile(filePath)) {
Files.delete(filePath);
successList.add(fileName);
} else {
failedList.add(fileName + " (文件不存在)");
}
} catch (Exception e) {
failedList.add(fileName + " (" + e.getMessage() + ")");
}
}
result.put("successCount", successList.size());
result.put("failedCount", failedList.size());
result.put("successFiles", successList);
result.put("failedFiles", failedList);
String message = String.format("批量删除完成: 成功 %d 个, 失败 %d 个",
successList.size(), failedList.size());
return ResponseEntity.ok(new ApiResponseVo<>(true, message, result));
} catch (Exception e) {
String errorMsg = "批量删除失败: " + e.getMessage();
System.err.println(errorMsg);
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponseVo<>(false, errorMsg, null));
}
}
/**
* 手动执行定时删除删除前3个月的文件
* POST /wms/file/cleanup
*/
@PostMapping("/cleanup")
@ResponseBody
public ResponseEntity<ApiResponseVo<Map<String, Object>>> manualCleanup() {
return performCleanup();
}
/**
* 定时删除任务 - 每3个月执行一次
* 删除前3个月的文件1-3个月前的文件
*/
@Scheduled(cron = "0 0 2 1 */3 *") // 每3个月的第1天凌晨2点执行
public void scheduledCleanup() {
System.out.println("=== 开始执行定时删除任务 ===");
System.out.println("执行时间: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
ResponseEntity<ApiResponseVo<Map<String, Object>>> response = performCleanup();
ApiResponseVo<Map<String, Object>> result = response.getBody();
if (result != null) {
System.out.println("定时删除结果: " + result.getMessage());
if (result.getData() != null) {
Map<String, Object> data = result.getData();
System.out.println("删除文件数量: " + data.get("deletedCount"));
System.out.println("删除的文件: " + data.get("deletedFiles"));
}
}
System.out.println("=== 定时删除任务完成 ===");
}
/**
* 执行清理操作
*/
private ResponseEntity<ApiResponseVo<Map<String, Object>>> performCleanup() {
try {
Path directory = Paths.get(directoryPath);
if (!Files.exists(directory)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "目录不存在: " + directoryPath, null));
}
// 计算时间范围删除1-3个月前的文件
LocalDateTime oneMonthAgo = LocalDateTime.now().minusMonths(1);
LocalDateTime threeMonthsAgo = LocalDateTime.now().minusMonths(3);
List<String> deletedFiles = new ArrayList<>();
int deletedCount = 0;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path file : stream) {
if (Files.isRegularFile(file)) {
try {
// 获取文件最后修改时间
LocalDateTime fileModifiedTime = LocalDateTime.ofInstant(
Files.getLastModifiedTime(file).toInstant(),
java.time.ZoneId.systemDefault()
);
// 如果文件修改时间在1-3个月前之间则删除
if (fileModifiedTime.isBefore(oneMonthAgo) && fileModifiedTime.isAfter(threeMonthsAgo)) {
Files.delete(file);
deletedFiles.add(file.getFileName().toString());
deletedCount++;
}
} catch (Exception e) {
System.err.println("删除文件失败: " + file.getFileName() + " - " + e.getMessage());
}
}
}
}
Map<String, Object> result = new HashMap<>();
result.put("deletedCount", deletedCount);
result.put("deletedFiles", deletedFiles);
result.put("cleanupTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
result.put("startTime", oneMonthAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
result.put("endTime", threeMonthsAgo.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
String message = String.format("清理完成: 删除了 %d 个前3个月的文件", deletedCount);
return ResponseEntity.ok(new ApiResponseVo<>(true, message, result));
} catch (Exception e) {
String errorMsg = "清理操作失败: " + e.getMessage();
System.err.println(errorMsg);
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponseVo<>(false, errorMsg, null));
}
}
/**
* 读取文件基本信息(不包含文件内容)
*/
private FileInfo readFileBasicInfo(Path filePath) throws IOException {
String fileName = filePath.getFileName().toString();
long fileSize = Files.size(filePath);
LocalDateTime lastModified = LocalDateTime.ofInstant(
Files.getLastModifiedTime(filePath).toInstant(),
java.time.ZoneId.systemDefault()
);
String lastModifiedStr = lastModified.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new FileInfo(fileName, fileSize, lastModifiedStr, filePath.toString());
}
/**
* 读取文件详细信息(包含文件内容)
*/
private FileDetailInfo readFileDetailInfo(Path filePath) throws IOException {
String fileName = filePath.getFileName().toString();
String fileContent = readFileContent(filePath);
long fileSize = Files.size(filePath);
LocalDateTime lastModified = LocalDateTime.ofInstant(
Files.getLastModifiedTime(filePath).toInstant(),
java.time.ZoneId.systemDefault()
);
String lastModifiedStr = lastModified.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return new FileDetailInfo(fileName, fileContent, fileSize, lastModifiedStr, filePath.toString());
}
/**
* 读取文件内容
*/
private String readFileContent(Path filePath) throws IOException {
try {
// 尝试使用UTF-8编码读取
return new String(Files.readAllBytes(filePath), "UTF-8");
} catch (Exception e) {
try {
// 如果UTF-8失败尝试使用系统默认编码
return new String(Files.readAllBytes(filePath));
} catch (Exception e2) {
return "文件读取失败: " + e2.getMessage();
}
}
}
/**
* 获取目录统计信息
* GET /wms/file/stats
*/
@GetMapping("/stats")
@ResponseBody
public ResponseEntity<ApiResponseVo<Map<String, Object>>> getDirectoryStats() {
try {
Path directory = Paths.get(directoryPath);
if (!Files.exists(directory)) {
return ResponseEntity.ok(new ApiResponseVo<>(false, "目录不存在: " + directoryPath, null));
}
Map<String, Object> stats = new HashMap<>();
int fileCount = 0;
long totalSize = 0;
List<String> fileNames = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path file : stream) {
if (Files.isRegularFile(file)) {
fileCount++;
totalSize += Files.size(file);
fileNames.add(file.getFileName().toString());
}
}
}
stats.put("directoryPath", directoryPath);
stats.put("fileCount", fileCount);
stats.put("totalSize", totalSize);
stats.put("totalSizeMB", String.format("%.2f MB", totalSize / (1024.0 * 1024.0)));
stats.put("fileNames", fileNames);
stats.put("lastUpdated", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
String message = String.format("目录统计: %d 个文件, 总大小 %.2f MB", fileCount, totalSize / (1024.0 * 1024.0));
return ResponseEntity.ok(new ApiResponseVo<>(true, message, stats));
} catch (Exception e) {
String errorMsg = "获取目录统计失败: " + e.getMessage();
System.err.println(errorMsg);
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponseVo<>(false, errorMsg, null));
}
}
}