From 593db69245fc49c8af16f5cdf137d50d278ebe16 Mon Sep 17 00:00:00 2001 From: "gayoun.park" Date: Wed, 8 Apr 2026 15:19:46 +0900 Subject: [PATCH] =?UTF-8?q?daniel=20file=20manager=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FileManagerService.java | 461 +++++++++--------- 1 file changed, 232 insertions(+), 229 deletions(-) diff --git a/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java b/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java index f20bf93..32b156e 100644 --- a/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java +++ b/src/main/java/com/kamco/cd/training/filemanager/service/FileManagerService.java @@ -33,6 +33,9 @@ public class FileManagerService { private static final String BASE_DATA_PATH = "/data"; private static final long MAX_PATH_LENGTH = 500; + @Value("${train.docker.base_path}") + private String basePath; + @Value("${train.docker.request_dir}") private String requestDir; @@ -53,7 +56,7 @@ public class FileManagerService { */ public FileManagerDto.ListFilesRes listFiles(FileManagerDto.ListFilesReq request) { String targetPath = - request.getDirectoryPath() != null ? request.getDirectoryPath() : BASE_DATA_PATH; + request.getDirectoryPath() != null ? request.getDirectoryPath() : BASE_DATA_PATH; boolean recursive = request.getRecursive() != null && request.getRecursive(); @@ -63,32 +66,32 @@ public class FileManagerService { } catch (IllegalArgumentException e) { log.debug("유효하지 않은 경로: {}", targetPath); return FileManagerDto.ListFilesRes.builder() - .directoryPath(targetPath) - .files(new ArrayList<>()) - .totalCount(0) - .totalSize(0L) - .build(); + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } Path directory = Paths.get(targetPath); if (!Files.exists(directory)) { log.debug("디렉토리가 존재하지 않습니다: {}", targetPath); return FileManagerDto.ListFilesRes.builder() - .directoryPath(targetPath) - .files(new ArrayList<>()) - .totalCount(0) - .totalSize(0L) - .build(); + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } if (!Files.isDirectory(directory)) { log.debug("디렉토리 경로가 아닙니다: {}", targetPath); return FileManagerDto.ListFilesRes.builder() - .directoryPath(targetPath) - .files(new ArrayList<>()) - .totalCount(0) - .totalSize(0L) - .build(); + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } List files = new ArrayList<>(); @@ -98,22 +101,22 @@ public class FileManagerService { if (recursive) { // 재귀적으로 모든 하위 파일 조회 Files.walkFileTree( - directory, - new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - files.add(createFileInfo(file)); - return FileVisitResult.CONTINUE; - } + directory, + new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + files.add(createFileInfo(file)); + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - if (!dir.equals(directory)) { - files.add(createFileInfo(dir)); - } - return FileVisitResult.CONTINUE; + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (!dir.equals(directory)) { + files.add(createFileInfo(dir)); } - }); + return FileVisitResult.CONTINUE; + } + }); } else { // 현재 디렉토리의 파일만 조회 try (Stream stream = Files.list(directory)) { @@ -131,19 +134,19 @@ public class FileManagerService { } catch (IOException e) { log.debug("파일 목록 조회 중 오류 발생: {}", targetPath, e); return FileManagerDto.ListFilesRes.builder() - .directoryPath(targetPath) - .files(new ArrayList<>()) - .totalCount(0) - .totalSize(0L) - .build(); + .directoryPath(targetPath) + .files(new ArrayList<>()) + .totalCount(0) + .totalSize(0L) + .build(); } return FileManagerDto.ListFilesRes.builder() - .directoryPath(targetPath) - .files(files) - .totalCount(files.size()) - .totalSize(totalSize) - .build(); + .directoryPath(targetPath) + .files(files) + .totalCount(files.size()) + .totalSize(totalSize) + .build(); } /** @@ -205,15 +208,15 @@ public class FileManagerService { } String message = - String.format("%d개 파일 삭제 성공, %d개 파일 삭제 실패", deletedFiles.size(), failedFiles.size()); + String.format("%d개 파일 삭제 성공, %d개 파일 삭제 실패", deletedFiles.size(), failedFiles.size()); return FileManagerDto.DeleteFileRes.builder() - .deletedFiles(deletedFiles) - .failedFiles(failedFiles) - .successCount(deletedFiles.size()) - .failureCount(failedFiles.size()) - .message(message) - .build(); + .deletedFiles(deletedFiles) + .failedFiles(failedFiles) + .successCount(deletedFiles.size()) + .failureCount(failedFiles.size()) + .message(message) + .build(); } /** FileInfo 객체 생성 */ @@ -222,45 +225,45 @@ public class FileManagerService { BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); return FileManagerDto.FileInfo.builder() - .fileName(path.getFileName().toString()) - .filePath(path.toString()) - .fileSize(attrs.isRegularFile() ? attrs.size() : null) - .isFile(attrs.isRegularFile()) - .isDirectory(attrs.isDirectory()) - .lastModified( - LocalDateTime.ofInstant( - Instant.ofEpochMilli(attrs.lastModifiedTime().toMillis()), - ZoneId.systemDefault())) - .readable(Files.isReadable(path)) - .writable(Files.isWritable(path)) - .build(); + .fileName(path.getFileName().toString()) + .filePath(path.toString()) + .fileSize(attrs.isRegularFile() ? attrs.size() : null) + .isFile(attrs.isRegularFile()) + .isDirectory(attrs.isDirectory()) + .lastModified( + LocalDateTime.ofInstant( + Instant.ofEpochMilli(attrs.lastModifiedTime().toMillis()), + ZoneId.systemDefault())) + .readable(Files.isReadable(path)) + .writable(Files.isWritable(path)) + .build(); } catch (IOException e) { log.warn("파일 정보 조회 실패: {}", path, e); return FileManagerDto.FileInfo.builder() - .fileName(path.getFileName().toString()) - .filePath(path.toString()) - .build(); + .fileName(path.getFileName().toString()) + .filePath(path.toString()) + .build(); } } /** 디렉토리 재귀 삭제 */ private void deleteDirectoryRecursively(Path directory) throws IOException { Files.walkFileTree( - directory, - new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } + directory, + new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); } /** 디렉토리가 비어있는지 확인 */ @@ -299,12 +302,12 @@ public class FileManagerService { // 모델이 존재하지 않으면 빈 데이터 반환 if (model == null) { return FileManagerDto.ModelFilePathRes.builder() - .modelUuid(modelUuid.toString()) - .requestPath(null) - .responsePath(null) - .requestFiles(new ArrayList<>()) - .responseFiles(new ArrayList<>()) - .build(); + .modelUuid(modelUuid.toString()) + .requestPath(null) + .responsePath(null) + .requestFiles(new ArrayList<>()) + .responseFiles(new ArrayList<>()) + .build(); } // request_path: tb_model_master.request_path 컬럼 값 사용 @@ -327,12 +330,12 @@ public class FileManagerService { List responseFiles = getFilesInDirectory(responsePath); return FileManagerDto.ModelFilePathRes.builder() - .modelUuid(modelUuid.toString()) - .requestPath(requestPath) - .responsePath(responsePath) - .requestFiles(requestFiles) - .responseFiles(responseFiles) - .build(); + .modelUuid(modelUuid.toString()) + .requestPath(requestPath) + .responsePath(responsePath) + .requestFiles(requestFiles) + .responseFiles(responseFiles) + .build(); } /** @@ -348,10 +351,10 @@ public class FileManagerService { // 데이터셋이 존재하지 않으면 빈 데이터 반환 if (dataset == null) { return FileManagerDto.DatasetFilePathRes.builder() - .datasetUuid(datasetUuid.toString()) - .datasetPath(null) - .files(new ArrayList<>()) - .build(); + .datasetUuid(datasetUuid.toString()) + .datasetPath(null) + .files(new ArrayList<>()) + .build(); } // dataset_path 컬럼이 있으면 사용, 없으면 request_dir + uuid 사용 @@ -364,10 +367,10 @@ public class FileManagerService { List files = getFilesInDirectory(datasetPath); return FileManagerDto.DatasetFilePathRes.builder() - .datasetUuid(datasetUuid.toString()) - .datasetPath(datasetPath) - .files(files) - .build(); + .datasetUuid(datasetUuid.toString()) + .datasetPath(datasetPath) + .files(files) + .build(); } /** @@ -383,35 +386,35 @@ public class FileManagerService { } catch (IllegalArgumentException e) { log.debug("유효하지 않은 경로: {}", directoryPath); return FileManagerDto.DirectoryCapacityRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .totalSize(0L) - .totalSizeFormatted("0 B") - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } Path directory = Paths.get(directoryPath); if (!Files.exists(directory)) { log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath); return FileManagerDto.DirectoryCapacityRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .totalSize(0L) - .totalSizeFormatted("0 B") - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } if (!Files.isDirectory(directory)) { log.debug("디렉토리 경로가 아닙니다: {}", directoryPath); return FileManagerDto.DirectoryCapacityRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .totalSize(0L) - .totalSizeFormatted("0 B") - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } final long[] totalSize = {0}; @@ -420,41 +423,41 @@ public class FileManagerService { try { Files.walkFileTree( - directory, - new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - totalSize[0] += attrs.size(); - fileCount[0]++; - return FileVisitResult.CONTINUE; - } + directory, + new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + totalSize[0] += attrs.size(); + fileCount[0]++; + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - if (!dir.equals(directory)) { - directoryCount[0]++; - } - return FileVisitResult.CONTINUE; + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (!dir.equals(directory)) { + directoryCount[0]++; } - }); + return FileVisitResult.CONTINUE; + } + }); } catch (IOException e) { log.debug("디렉토리 용량 체크 중 오류 발생: {}", directoryPath, e); return FileManagerDto.DirectoryCapacityRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .totalSize(0L) - .totalSizeFormatted("0 B") - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .totalSize(0L) + .totalSizeFormatted("0 B") + .build(); } return FileManagerDto.DirectoryCapacityRes.builder() - .directoryPath(directoryPath) - .fileCount(fileCount[0]) - .directoryCount(directoryCount[0]) - .totalSize(totalSize[0]) - .totalSizeFormatted(formatFileSize(totalSize[0])) - .build(); + .directoryPath(directoryPath) + .fileCount(fileCount[0]) + .directoryCount(directoryCount[0]) + .totalSize(totalSize[0]) + .totalSizeFormatted(formatFileSize(totalSize[0])) + .build(); } /** @@ -471,18 +474,18 @@ public class FileManagerService { for (String modelNo : modelNumbers) { // model_no로 가장 최근 모델 조회 (del_yn = false) List models = - modelMngRepository.findByModelNoAndDelYnOrderByCreatedDttmDesc(modelNo, false); + modelMngRepository.findByModelNoAndDelYnOrderByCreatedDttmDesc(modelNo, false); if (models.isEmpty()) { // 모델이 없으면 대기 상태 modelStatuses.add( - FileManagerDto.ModelExecutionStatusRes.builder() - .modelNo(modelNo) - .statusMessage(modelNo + " 모델은 대기 중입니다.") - .step1State(null) - .step2State(null) - .currentStep(null) - .build()); + FileManagerDto.ModelExecutionStatusRes.builder() + .modelNo(modelNo) + .statusMessage(modelNo + " 모델은 대기 중입니다.") + .step1State(null) + .step2State(null) + .currentStep(null) + .build()); continue; } @@ -514,19 +517,19 @@ public class FileManagerService { } modelStatuses.add( - FileManagerDto.ModelExecutionStatusRes.builder() - .modelNo(modelNo) - .statusMessage(statusMessage) - .step1State(step1State) - .step2State(step2State) - .currentStep(currentStep) - .build()); + FileManagerDto.ModelExecutionStatusRes.builder() + .modelNo(modelNo) + .statusMessage(statusMessage) + .step1State(step1State) + .step2State(step2State) + .currentStep(currentStep) + .build()); } return FileManagerDto.AllModelsExecutionStatusRes.builder() - .modelStatuses(modelStatuses) - .runningCount(runningCount) - .build(); + .modelStatuses(modelStatuses) + .runningCount(runningCount) + .build(); } /** 디렉토리 내 파일 목록 조회 (내부 사용) */ @@ -567,49 +570,49 @@ public class FileManagerService { } /** - * 저장공간 정보 조회 (남은 공간 포함) 고정 경로: /home/kcomu/data + * 저장공간 정보 조회 (남은 공간 포함) 고정 경로: train.docker.base_path 설정값 사용 * * @return 저장공간 정보 (사용량, 남은 공간, 디스크 용량) */ public FileManagerDto.StorageSpaceRes getStorageSpaceInfo() { - // 고정 경로: /home/kcomu/data - String directoryPath = "/home/kcomu/data"; + // 설정값에서 경로 가져오기 (train.docker.base_path) + String directoryPath = basePath; Path directory = Paths.get(directoryPath); if (!Files.exists(directory)) { log.debug("디렉토리가 존재하지 않습니다: {}", directoryPath); return FileManagerDto.StorageSpaceRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .usedSize(0L) - .usedSizeFormatted("0 B") - .totalDiskSpace(0L) - .totalDiskSpaceFormatted("0 B") - .freeSpace(0L) - .freeSpaceFormatted("0 B") - .usableSpace(0L) - .usableSpaceFormatted("0 B") - .usagePercentage(0.0) - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .usedSize(0L) + .usedSizeFormatted("0 B") + .totalDiskSpace(0L) + .totalDiskSpaceFormatted("0 B") + .freeSpace(0L) + .freeSpaceFormatted("0 B") + .usableSpace(0L) + .usableSpaceFormatted("0 B") + .usagePercentage(0.0) + .build(); } if (!Files.isDirectory(directory)) { log.debug("디렉토리 경로가 아닙니다: {}", directoryPath); return FileManagerDto.StorageSpaceRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .usedSize(0L) - .usedSizeFormatted("0 B") - .totalDiskSpace(0L) - .totalDiskSpaceFormatted("0 B") - .freeSpace(0L) - .freeSpaceFormatted("0 B") - .usableSpace(0L) - .usableSpaceFormatted("0 B") - .usagePercentage(0.0) - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .usedSize(0L) + .usedSizeFormatted("0 B") + .totalDiskSpace(0L) + .totalDiskSpaceFormatted("0 B") + .freeSpace(0L) + .freeSpaceFormatted("0 B") + .usableSpace(0L) + .usableSpaceFormatted("0 B") + .usagePercentage(0.0) + .build(); } // 디렉토리 사용량 계산 (재귀적으로 모든 파일 크기 합산) @@ -619,39 +622,39 @@ public class FileManagerService { try { Files.walkFileTree( - directory, - new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - usedSize[0] += attrs.size(); - fileCount[0]++; - return FileVisitResult.CONTINUE; - } + directory, + new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + usedSize[0] += attrs.size(); + fileCount[0]++; + return FileVisitResult.CONTINUE; + } - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - if (!dir.equals(directory)) { - directoryCount[0]++; - } - return FileVisitResult.CONTINUE; + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (!dir.equals(directory)) { + directoryCount[0]++; } - }); + return FileVisitResult.CONTINUE; + } + }); } catch (IOException e) { log.debug("디렉토리 용량 계산 중 오류 발생: {}", directoryPath, e); return FileManagerDto.StorageSpaceRes.builder() - .directoryPath(directoryPath) - .fileCount(0) - .directoryCount(0) - .usedSize(0L) - .usedSizeFormatted("0 B") - .totalDiskSpace(0L) - .totalDiskSpaceFormatted("0 B") - .freeSpace(0L) - .freeSpaceFormatted("0 B") - .usableSpace(0L) - .usableSpaceFormatted("0 B") - .usagePercentage(0.0) - .build(); + .directoryPath(directoryPath) + .fileCount(0) + .directoryCount(0) + .usedSize(0L) + .usedSizeFormatted("0 B") + .totalDiskSpace(0L) + .totalDiskSpaceFormatted("0 B") + .freeSpace(0L) + .freeSpaceFormatted("0 B") + .usableSpace(0L) + .usableSpaceFormatted("0 B") + .usagePercentage(0.0) + .build(); } // 디스크 공간 정보 조회 (FileStore 사용) @@ -677,18 +680,18 @@ public class FileManagerService { } return FileManagerDto.StorageSpaceRes.builder() - .directoryPath(directoryPath) - .fileCount(fileCount[0]) - .directoryCount(directoryCount[0]) - .usedSize(usedSize[0]) - .usedSizeFormatted(formatFileSize(usedSize[0])) - .totalDiskSpace(totalDiskSpace) - .totalDiskSpaceFormatted(formatFileSize(totalDiskSpace)) - .freeSpace(freeSpace) - .freeSpaceFormatted(formatFileSize(freeSpace)) - .usableSpace(usableSpace) - .usableSpaceFormatted(formatFileSize(usableSpace)) - .usagePercentage(Math.round(usagePercentage * 100.0) / 100.0) - .build(); + .directoryPath(directoryPath) + .fileCount(fileCount[0]) + .directoryCount(directoryCount[0]) + .usedSize(usedSize[0]) + .usedSizeFormatted(formatFileSize(usedSize[0])) + .totalDiskSpace(totalDiskSpace) + .totalDiskSpaceFormatted(formatFileSize(totalDiskSpace)) + .freeSpace(freeSpace) + .freeSpaceFormatted(formatFileSize(freeSpace)) + .usableSpace(usableSpace) + .usableSpaceFormatted(formatFileSize(usableSpace)) + .usagePercentage(Math.round(usagePercentage * 100.0) / 100.0) + .build(); } }