daniel file manager 수정 반영

This commit is contained in:
2026-04-08 15:19:46 +09:00
parent 5651fd7819
commit 593db69245

View File

@@ -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<FileManagerDto.FileInfo> 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<Path> 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<FileManagerDto.FileInfo> 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<FileManagerDto.FileInfo> 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<ModelMasterEntity> 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();
}
}