납품 폴더 조회 api 추가 #167

Merged
teddy merged 1 commits from feat/training_260324 into develop 2026-03-24 17:19:39 +09:00
3 changed files with 277 additions and 0 deletions

View File

@@ -6,6 +6,8 @@ import com.kamco.cd.training.dataset.dto.DatasetObjDto;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetClass; import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetClass;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetStorage; import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetStorage;
import com.kamco.cd.training.dataset.service.DatasetService; import com.kamco.cd.training.dataset.service.DatasetService;
import com.kamco.cd.training.model.dto.FileDto.FoldersDto;
import com.kamco.cd.training.model.dto.FileDto.SrchFoldersDto;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
@@ -248,4 +250,23 @@ public class DatasetApiController {
String path = datasetService.getFilePathByUUIDPathType(uuid, pathType); String path = datasetService.getFilePathByUUIDPathType(uuid, pathType);
return datasetService.getFilePathByFile(path); return datasetService.getFilePathByFile(path);
} }
@Operation(summary = "납품 폴더 조회", description = "납품 폴더 조회 API")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "조회 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = Page.class))),
@ApiResponse(responseCode = "404", description = "조회 오류", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping("/folder-list")
public ApiResponseDto<FoldersDto> getDir(@RequestBody SrchFoldersDto srchDto) throws IOException {
return ApiResponseDto.createOK(datasetService.getFolderAll(srchDto));
}
} }

View File

@@ -18,8 +18,11 @@ import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetClass;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetObjRegDto; import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetObjRegDto;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetStorage; import com.kamco.cd.training.dataset.dto.DatasetObjDto.DatasetStorage;
import com.kamco.cd.training.dataset.dto.DatasetObjDto.SearchReq; import com.kamco.cd.training.dataset.dto.DatasetObjDto.SearchReq;
import com.kamco.cd.training.model.dto.FileDto.FoldersDto;
import com.kamco.cd.training.model.dto.FileDto.SrchFoldersDto;
import com.kamco.cd.training.postgres.core.DatasetCoreService; import com.kamco.cd.training.postgres.core.DatasetCoreService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
@@ -27,6 +30,8 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -506,4 +511,98 @@ public class DatasetService {
} }
} }
} }
/**
* 폴더 조회
*
* @param srchDto 폴더 경로
* @return 폴더 리스트
* @throws IOException
*/
public FoldersDto getFolderAll(SrchFoldersDto srchDto) throws IOException {
File dir = new File(srchDto.getDirPath() == null ? "/" : srchDto.getDirPath());
// 존재 + 디렉토리 체크
if (!dir.exists() || !dir.isDirectory()) {
throw new RuntimeException("Invalid path");
}
// 권한 없을때
if (!dir.canRead()) {
throw new RuntimeException("Permission denied");
}
String canonicalPath = dir.getCanonicalPath();
File[] files = dir.listFiles();
if (files == null) {
return new FoldersDto(canonicalPath, 0, 0, Collections.emptyList());
}
List<FIleChecker.Folder> folders = new ArrayList<>();
int folderTotCnt = 0;
int folderErrTotCnt = 0;
for (File f : files) {
// 숨김 제외
if (f.isHidden()) continue;
if (f.isDirectory()) {
// 폴더 개수 증가
folderTotCnt++;
// 폴더 유효성 여부 (기본 true, 이후 검증 로직으로 변경 가능)
boolean isValid = true;
// 유효하지 않은 폴더 카운트 증가
if (!isValid) folderErrTotCnt++;
// 현재 폴더 이름 (ex: train, images 등)
String folderNm = f.getName();
// 부모 경로 (ex: /data/datasets)
String parentPath = f.getParent();
// 부모 폴더 이름 (ex: datasets)
String parentFolderNm = new File(parentPath).getName();
// 전체 절대 경로 (ex: /data/datasets/train)
String fullPath = f.getAbsolutePath();
// 폴더 깊이 (경로 기준 depth)
// ex: /a/b/c → depth = 3
int depth = f.toPath().getNameCount();
// 하위 폴더 개수
long childCnt = FIleChecker.getChildFolderCount(f);
// 마지막 수정 시간 (문자열 포맷)
String lastModified = FIleChecker.getLastModified(f);
// Folder DTO 생성 및 리스트에 추가
folders.add(
new FIleChecker.Folder(
folderNm, // 폴더명
parentFolderNm, // 부모 폴더명
parentPath, // 부모 경로
fullPath, // 전체 경로
depth, // 깊이
childCnt, // 하위 폴더 개수
lastModified, // 수정일시
isValid // 유효성 여부
));
}
}
// 폴더 정렬
folders.sort(
Comparator.comparing(FIleChecker.Folder::getFolderNm, String.CASE_INSENSITIVE_ORDER));
return new FoldersDto(canonicalPath, folderTotCnt, folderErrTotCnt, folders);
}
} }

View File

@@ -0,0 +1,157 @@
package com.kamco.cd.training.model.dto;
import com.kamco.cd.training.common.utils.FIleChecker;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
public class FileDto {
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class SrchFoldersDto {
@Schema(description = "디렉토리경로(ROOT:/)", example = "")
@NotNull
private String dirPath = "/";
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class SrchFilesDto {
@Schema(description = "디렉토리경로", example = "D:\\kamco\\2022\\캠코_2021_2022_34602060_D1")
@NotNull
private String dirPath;
@Schema(description = "전체(*), cpg,dbf,geojson등", example = "*")
@NotNull
private String extension;
@Schema(description = "파일명(name), 최종수정일(date)", example = "name")
@NotNull
private String sortType;
@Schema(description = "파일시작위치", example = "1")
@NotNull
private Integer startPos;
@Schema(description = "파일종료위치", example = "100")
@NotNull
private Integer endPos;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class SrchFilesDepthDto extends SrchFilesDto {
@Schema(description = "최대폴더Depth", example = "5")
@NotNull
private Integer maxDepth;
}
@Schema(name = "FolderDto", description = "폴더 정보")
@Getter
public static class FolderDto {
private final String folderNm;
private final String parentFolderNm;
private final String parentPath;
private final String fullPath;
private final int depth;
private final long childCnt;
private final String lastModified;
private final Boolean isValid;
public FolderDto(
String folderNm,
String parentFolderNm,
String parentPath,
String fullPath,
int depth,
long childCnt,
String lastModified,
Boolean isValid) {
this.folderNm = folderNm;
this.parentFolderNm = parentFolderNm;
this.parentPath = parentPath;
this.fullPath = fullPath;
this.depth = depth;
this.childCnt = childCnt;
this.lastModified = lastModified;
this.isValid = isValid;
}
}
@Schema(name = "FoldersDto", description = "폴더목록 정보")
@Getter
public static class FoldersDto {
private final String dirPath;
private final int folderTotCnt;
private final int folderErrTotCnt;
private final List<FIleChecker.Folder> folders;
public FoldersDto(
String dirPath, int folderTotCnt, int folderErrTotCnt, List<FIleChecker.Folder> folders) {
this.dirPath = dirPath;
this.folderTotCnt = folderTotCnt;
this.folderErrTotCnt = folderErrTotCnt;
this.folders = folders;
}
}
@Schema(name = "File Basic", description = "파일 기본 정보")
@Getter
public static class Basic {
private final String fileNm;
private final String parentFolderNm;
private final String parentPath;
private final String fullPath;
private final String extension;
private final long fileSize;
private final String lastModified;
public Basic(
String fileNm,
String parentFolderNm,
String parentPath,
String fullPath,
String extension,
long fileSize,
String lastModified) {
this.fileNm = fileNm;
this.parentFolderNm = parentFolderNm;
this.parentPath = parentPath;
this.fullPath = fullPath;
this.extension = extension;
this.fileSize = fileSize;
this.lastModified = lastModified;
}
}
@Schema(name = "FilesDto", description = "파일 목록 정보")
@Getter
public static class FilesDto {
private final String dirPath;
private final int fileTotCnt;
private final long fileTotSize;
private final List<FIleChecker.Basic> files;
public FilesDto(
String dirPath, int fileTotCnt, long fileTotSize, List<FIleChecker.Basic> files) {
this.dirPath = dirPath;
this.fileTotCnt = fileTotCnt;
this.fileTotSize = fileTotSize;
this.files = files;
}
}
}