중복페어 조회, 선택삭제, 파일삭제, 중복파일삭제 추가
This commit is contained in:
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.mapsheet;
|
|||||||
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
|
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
|
||||||
import com.kamco.cd.kamcoback.code.service.CommonCodeService;
|
import com.kamco.cd.kamcoback.code.service.CommonCodeService;
|
||||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||||
|
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto;
|
||||||
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FilesDto;
|
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FilesDto;
|
||||||
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FoldersDto;
|
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FoldersDto;
|
||||||
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto;
|
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto;
|
||||||
@@ -16,6 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
|||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -24,6 +26,8 @@ import org.springframework.web.bind.annotation.RequestPart;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Tag(name = "영상 관리", description = "영상 관리 API")
|
@Tag(name = "영상 관리", description = "영상 관리 API")
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -110,6 +114,27 @@ public class MapSheetMngFileCheckerApiController {
|
|||||||
mapSheetMngFileCheckerService.deleteDuplicate(filePath, fileName));
|
mapSheetMngFileCheckerService.deleteDuplicate(filePath, fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 중복 페어 조회: 특정 경로에서 같은 베이스명의 tif/tfw 후보를 반환
|
||||||
|
@Operation(summary = "중복 페어 조회", description = "경로와 베이스명으로 중복된 tif/tfw 후보 조회")
|
||||||
|
@PostMapping("/duplicates")
|
||||||
|
public ApiResponseDto<List<FileDto.Basic>> findDuplicates(
|
||||||
|
@RequestParam("targetPath") String targetPath,
|
||||||
|
@RequestParam("baseName") String baseName) {
|
||||||
|
return ApiResponseDto.createOK(
|
||||||
|
mapSheetMngFileCheckerService.findDuplicatePair(targetPath, baseName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 선택 삭제: ID 목록으로 중복 항목 삭제
|
||||||
|
public static class DeleteDuplicatesReq {
|
||||||
|
public List<Long> ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "중복 파일 선택 삭제", description = "중복 후보 중 선택한 항목만 삭제")
|
||||||
|
@DeleteMapping("/duplicates")
|
||||||
|
public ApiResponseDto<List<Long>> deleteDuplicates(@RequestBody DeleteDuplicatesReq req) {
|
||||||
|
return ApiResponseDto.createOK(mapSheetMngFileCheckerService.deleteDuplicatesByIds(req.ids));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Operation(summary = "지정폴더(하위폴더포함) 파일목록 조회", description = "지정폴더(하위폴더포함) 파일목록 조회")
|
@Operation(summary = "지정폴더(하위폴더포함) 파일목록 조회", description = "지정폴더(하위폴더포함) 파일목록 조회")
|
||||||
@ApiResponses(
|
@ApiResponses(
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.attribute.FileTime;
|
import java.nio.file.attribute.FileTime;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -319,12 +321,20 @@ public class MapSheetMngFileCheckerService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public String uploadFile(MultipartFile file, String targetPath, boolean overwrite, Long hstUid) {
|
public String uploadFile(MultipartFile file, String targetPath, boolean overwrite, Long hstUid) {
|
||||||
|
ZonedDateTime startAt = ZonedDateTime.now();
|
||||||
|
if (hstUid != null) {
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckStart(hstUid);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// 파일 유효성 검증
|
// 파일 유효성 검증
|
||||||
if (file == null || file.isEmpty()) {
|
if (file == null || file.isEmpty()) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "SIZEERROR");
|
||||||
throw new ValidationException("업로드 파일이 비어있습니다.");
|
throw new ValidationException("업로드 파일이 비어있습니다.");
|
||||||
}
|
}
|
||||||
if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) {
|
if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("파일명이 유효하지 않습니다.");
|
throw new ValidationException("파일명이 유효하지 않습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,10 +377,11 @@ public class MapSheetMngFileCheckerService {
|
|||||||
String parentPathStr = path.getParent() != null ? path.getParent().toString() : "";
|
String parentPathStr = path.getParent() != null ? path.getParent().toString() : "";
|
||||||
boolean dbExists =
|
boolean dbExists =
|
||||||
mapSheetMngFileRepository.existsByFileNameAndFilePath(filename, parentPathStr);
|
mapSheetMngFileRepository.existsByFileNameAndFilePath(filename, parentPathStr);
|
||||||
// boolean fileExists = Files.exists(path); // 파일 시스템 존재 여부는 체크하지 않음 (DB 기준)
|
|
||||||
|
|
||||||
// 이미 존재하는 경우 처리 (DB에만 있는 경우 체크)
|
// 이미 존재하는 경우 처리 (DB에만 있는 경우 체크)
|
||||||
if (!overwrite && dbExists) {
|
if (!overwrite && dbExists) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "DUPLICATE");
|
||||||
throw new DuplicateFileException("동일한 파일이 이미 존재합니다 (DB): " + path.getFileName());
|
throw new DuplicateFileException("동일한 파일이 이미 존재합니다 (DB): " + path.getFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,22 +393,31 @@ public class MapSheetMngFileCheckerService {
|
|||||||
// 업로드 파일 저장(덮어쓰기 허용 시 replace)
|
// 업로드 파일 저장(덮어쓰기 허용 시 replace)
|
||||||
file.transferTo(path.toFile());
|
file.transferTo(path.toFile());
|
||||||
|
|
||||||
|
if (file.getSize() == 0) {
|
||||||
|
Files.deleteIfExists(path);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "SIZEERROR");
|
||||||
|
throw new ValidationException("유효하지 않은 파일입니다 (크기 0): " + path.getFileName());
|
||||||
|
}
|
||||||
|
|
||||||
if ("tfw".equals(ext)) {
|
if ("tfw".equals(ext)) {
|
||||||
// TFW 검증
|
|
||||||
boolean tfwOk = FIleChecker.checkTfw(path.toString());
|
boolean tfwOk = FIleChecker.checkTfw(path.toString());
|
||||||
if (!tfwOk) {
|
if (!tfwOk) {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException(
|
throw new ValidationException(
|
||||||
"유효하지 않은 TFW 파일입니다 (6줄 숫자 형식 검증 실패): " + path.getFileName());
|
"유효하지 않은 TFW 파일입니다 (6줄 숫자 형식 검증 실패): " + path.getFileName());
|
||||||
}
|
}
|
||||||
// 안내: 같은 베이스의 TIF가 없으면 추후 TIF 업로드 필요
|
|
||||||
if (!Files.exists(tifPath)) {
|
if (!Files.exists(tifPath)) {
|
||||||
// DB 메타 저장은 진행 (향후 쌍 검증 위해)
|
// TIF가 없으면 페어 없음
|
||||||
saveUploadMeta(path, hstUid);
|
saveUploadMeta(path, hstUid);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "NOTPAIR");
|
||||||
return "TFW 업로드 성공 (매칭되는 TIF가 아직 없습니다).";
|
return "TFW 업로드 성공 (매칭되는 TIF가 아직 없습니다).";
|
||||||
}
|
}
|
||||||
// TIF가 존재하면 쌍 요건 충족
|
|
||||||
saveUploadMeta(path, hstUid);
|
saveUploadMeta(path, hstUid);
|
||||||
|
if (hstUid != null) mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "DONE");
|
||||||
return "TFW 업로드 성공";
|
return "TFW 업로드 성공";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,34 +426,46 @@ public class MapSheetMngFileCheckerService {
|
|||||||
boolean isValidTif = FIleChecker.cmmndGdalInfo(path.toString());
|
boolean isValidTif = FIleChecker.cmmndGdalInfo(path.toString());
|
||||||
if (!isValidTif) {
|
if (!isValidTif) {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("유효하지 않은 TIF 파일입니다 (GDAL 검증 실패): " + path.getFileName());
|
throw new ValidationException("유효하지 않은 TIF 파일입니다 (GDAL 검증 실패): " + path.getFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TFW 존재/검증
|
// TFW 존재/검증
|
||||||
if (!Files.exists(tfwPath)) {
|
if (!Files.exists(tfwPath)) {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "NOTPAIR");
|
||||||
throw new ValidationException("TFW 파일이 존재하지 않습니다: " + tfwPath.getFileName());
|
throw new ValidationException("TFW 파일이 존재하지 않습니다: " + tfwPath.getFileName());
|
||||||
}
|
}
|
||||||
boolean tfwOk = FIleChecker.checkTfw(tfwPath.toString());
|
boolean tfwOk = FIleChecker.checkTfw(tfwPath.toString());
|
||||||
if (!tfwOk) {
|
if (!tfwOk) {
|
||||||
Files.deleteIfExists(path);
|
Files.deleteIfExists(path);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException(
|
throw new ValidationException(
|
||||||
"유효하지 않은 TFW 파일입니다 (6줄 숫자 형식 검증 실패): " + tfwPath.getFileName());
|
"유효하지 않은 TFW 파일입니다 (6줄 숫자 형식 검증 실패): " + tfwPath.getFileName());
|
||||||
}
|
}
|
||||||
saveUploadMeta(path, hstUid);
|
saveUploadMeta(path, hstUid);
|
||||||
|
if (hstUid != null) mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "DONE");
|
||||||
return "TIF 업로드 성공";
|
return "TIF 업로드 성공";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 기타 확장자: 저장만 하고 메타 기록
|
// 기타 확장자: 저장만 하고 메타 기록
|
||||||
saveUploadMeta(path, hstUid);
|
saveUploadMeta(path, hstUid);
|
||||||
|
if (hstUid != null) mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "DONE");
|
||||||
|
|
||||||
return "업로드 성공";
|
return "업로드 성공";
|
||||||
} catch (ValidationException | DuplicateFileException e) {
|
} catch (ValidationException | DuplicateFileException e) {
|
||||||
// 비즈니스 예외는 그대로 던짐
|
// 비즈니스 예외는 그대로 던짐
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new IllegalArgumentException("파일 I/O 처리 실패: " + e.getMessage(), e);
|
throw new IllegalArgumentException("파일 I/O 처리 실패: " + e.getMessage(), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new IllegalArgumentException("파일 업로드 처리 중 오류 발생: " + e.getMessage(), e);
|
throw new IllegalArgumentException("파일 업로드 처리 중 오류 발생: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,6 +477,9 @@ public class MapSheetMngFileCheckerService {
|
|||||||
String targetPath,
|
String targetPath,
|
||||||
boolean overwrite,
|
boolean overwrite,
|
||||||
Long hstUid) {
|
Long hstUid) {
|
||||||
|
if (hstUid != null) {
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckStart(hstUid);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
log.info(
|
log.info(
|
||||||
"uploadPair 시작 - targetPath: {}, overwrite: {}, hstUid: {}",
|
"uploadPair 시작 - targetPath: {}, overwrite: {}, hstUid: {}",
|
||||||
@@ -454,15 +489,23 @@ public class MapSheetMngFileCheckerService {
|
|||||||
|
|
||||||
// 파일 유효성 검증
|
// 파일 유효성 검증
|
||||||
if (tfwFile == null || tfwFile.isEmpty()) {
|
if (tfwFile == null || tfwFile.isEmpty()) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "NOFILE");
|
||||||
throw new ValidationException("TFW 파일이 비어있습니다.");
|
throw new ValidationException("TFW 파일이 비어있습니다.");
|
||||||
}
|
}
|
||||||
if (tifFile == null || tifFile.isEmpty()) {
|
if (tifFile == null || tifFile.isEmpty()) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "NOFILE");
|
||||||
throw new ValidationException("TIF 파일이 비어있습니다.");
|
throw new ValidationException("TIF 파일이 비어있습니다.");
|
||||||
}
|
}
|
||||||
if (tfwFile.getOriginalFilename() == null || tfwFile.getOriginalFilename().isEmpty()) {
|
if (tfwFile.getOriginalFilename() == null || tfwFile.getOriginalFilename().isEmpty()) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("TFW 파일명이 유효하지 않습니다.");
|
throw new ValidationException("TFW 파일명이 유효하지 않습니다.");
|
||||||
}
|
}
|
||||||
if (tifFile.getOriginalFilename() == null || tifFile.getOriginalFilename().isEmpty()) {
|
if (tifFile.getOriginalFilename() == null || tifFile.getOriginalFilename().isEmpty()) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("TIF 파일명이 유효하지 않습니다.");
|
throw new ValidationException("TIF 파일명이 유효하지 않습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,13 +535,11 @@ public class MapSheetMngFileCheckerService {
|
|||||||
String tfwBase = FilenameUtils.getBaseName(tfwPath.getFileName().toString());
|
String tfwBase = FilenameUtils.getBaseName(tfwPath.getFileName().toString());
|
||||||
String tifBase = FilenameUtils.getBaseName(tifPath.getFileName().toString());
|
String tifBase = FilenameUtils.getBaseName(tifPath.getFileName().toString());
|
||||||
if (!tfwBase.equalsIgnoreCase(tifBase)) {
|
if (!tfwBase.equalsIgnoreCase(tifBase)) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "NOTPAIR");
|
||||||
throw new ValidationException("TFW/TIF 파일명이 동일한 베이스가 아닙니다.");
|
throw new ValidationException("TFW/TIF 파일명이 동일한 베이스가 아닙니다.");
|
||||||
}
|
}
|
||||||
// 디렉토리는 이미 생성되었으므로 추가 생성 불필요
|
|
||||||
// if (tfwPath.getParent() != null) Files.createDirectories(tfwPath.getParent());
|
|
||||||
// if (tifPath.getParent() != null) Files.createDirectories(tifPath.getParent());
|
|
||||||
|
|
||||||
// DB 중복 체크 및 overwrite 처리 (각 파일별)
|
|
||||||
String parentPathStr = basePath.toString();
|
String parentPathStr = basePath.toString();
|
||||||
String tfwName = tfwPath.getFileName().toString();
|
String tfwName = tfwPath.getFileName().toString();
|
||||||
String tifName = tifPath.getFileName().toString();
|
String tifName = tifPath.getFileName().toString();
|
||||||
@@ -507,6 +548,8 @@ public class MapSheetMngFileCheckerService {
|
|||||||
boolean tifDbExists =
|
boolean tifDbExists =
|
||||||
mapSheetMngFileRepository.existsByFileNameAndFilePath(tifName, parentPathStr);
|
mapSheetMngFileRepository.existsByFileNameAndFilePath(tifName, parentPathStr);
|
||||||
if (!overwrite && (tfwDbExists || tifDbExists)) {
|
if (!overwrite && (tfwDbExists || tifDbExists)) {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "DUPLICATE");
|
||||||
throw new DuplicateFileException("동일한 파일이 이미 존재합니다 (DB): " + tfwName + ", " + tifName);
|
throw new DuplicateFileException("동일한 파일이 이미 존재합니다 (DB): " + tfwName + ", " + tifName);
|
||||||
}
|
}
|
||||||
if (overwrite) {
|
if (overwrite) {
|
||||||
@@ -522,6 +565,15 @@ public class MapSheetMngFileCheckerService {
|
|||||||
tifFile.transferTo(tifPath.toFile());
|
tifFile.transferTo(tifPath.toFile());
|
||||||
log.info("파일 저장 완료");
|
log.info("파일 저장 완료");
|
||||||
|
|
||||||
|
// 0 바이트 체크
|
||||||
|
if (Files.size(tfwPath) == 0 || Files.size(tifPath) == 0) {
|
||||||
|
Files.deleteIfExists(tfwPath);
|
||||||
|
Files.deleteIfExists(tifPath);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "SIZEERROR");
|
||||||
|
throw new ValidationException("업로드 파일 크기가 0입니다.");
|
||||||
|
}
|
||||||
|
|
||||||
// 검증
|
// 검증
|
||||||
log.info("TFW 파일 검증 시작: {}", tfwPath);
|
log.info("TFW 파일 검증 시작: {}", tfwPath);
|
||||||
boolean tfwOk = FIleChecker.checkTfw(tfwPath.toString());
|
boolean tfwOk = FIleChecker.checkTfw(tfwPath.toString());
|
||||||
@@ -529,6 +581,8 @@ public class MapSheetMngFileCheckerService {
|
|||||||
log.warn("TFW 파일 검증 실패: {}", tfwName);
|
log.warn("TFW 파일 검증 실패: {}", tfwName);
|
||||||
Files.deleteIfExists(tfwPath);
|
Files.deleteIfExists(tfwPath);
|
||||||
Files.deleteIfExists(tifPath);
|
Files.deleteIfExists(tifPath);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("유효하지 않은 TFW 파일입니다 (6줄 숫자 형식 검증 실패): " + tfwName);
|
throw new ValidationException("유효하지 않은 TFW 파일입니다 (6줄 숫자 형식 검증 실패): " + tfwName);
|
||||||
}
|
}
|
||||||
log.info("TFW 파일 검증 성공");
|
log.info("TFW 파일 검증 성공");
|
||||||
@@ -539,6 +593,8 @@ public class MapSheetMngFileCheckerService {
|
|||||||
log.warn("TIF 파일 검증 실패: {}", tifName);
|
log.warn("TIF 파일 검증 실패: {}", tifName);
|
||||||
Files.deleteIfExists(tfwPath);
|
Files.deleteIfExists(tfwPath);
|
||||||
Files.deleteIfExists(tifPath);
|
Files.deleteIfExists(tifPath);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("유효하지 않은 TIF 파일입니다 (GDAL 검증 실패): " + tifName);
|
throw new ValidationException("유효하지 않은 TIF 파일입니다 (GDAL 검증 실패): " + tifName);
|
||||||
}
|
}
|
||||||
log.info("TIF 파일 검증 성공");
|
log.info("TIF 파일 검증 성공");
|
||||||
@@ -548,8 +604,11 @@ public class MapSheetMngFileCheckerService {
|
|||||||
saveUploadMeta(tfwPath, hstUid);
|
saveUploadMeta(tfwPath, hstUid);
|
||||||
saveUploadMeta(tifPath, hstUid);
|
saveUploadMeta(tifPath, hstUid);
|
||||||
log.info("메타 데이터 저장 완료");
|
log.info("메타 데이터 저장 완료");
|
||||||
|
if (hstUid != null) mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "DONE");
|
||||||
return "TFW/TIF 페어 업로드 성공";
|
return "TFW/TIF 페어 업로드 성공";
|
||||||
} else {
|
} else {
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new ValidationException("targetPath는 디렉토리여야 합니다.");
|
throw new ValidationException("targetPath는 디렉토리여야 합니다.");
|
||||||
}
|
}
|
||||||
} catch (ValidationException | DuplicateFileException e) {
|
} catch (ValidationException | DuplicateFileException e) {
|
||||||
@@ -558,13 +617,62 @@ public class MapSheetMngFileCheckerService {
|
|||||||
throw e;
|
throw e;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("파일 I/O 처리 실패: {}", e.getMessage(), e);
|
log.error("파일 I/O 처리 실패: {}", e.getMessage(), e);
|
||||||
throw new IllegalArgumentException("파일 I/O 처리 실패: " + e.getMessage(), e);
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
|
throw new IllegalArgumentException("파일 업로드 처리 중 오류 발생: " + e.getMessage(), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("파일 업로드 처리 중 예상치 못한 오류 발생: {}", e.getMessage(), e);
|
log.error("파일 업로드 처리 중 예상치 못한 오류 발생: {}", e.getMessage(), e);
|
||||||
|
if (hstUid != null)
|
||||||
|
mapSheetMngFileCheckerCoreService.updateHstSyncCheckEnd(hstUid, "TYPEERROR");
|
||||||
throw new IllegalArgumentException("파일 업로드 처리 중 오류 발생: " + e.getMessage(), e);
|
throw new IllegalArgumentException("파일 업로드 처리 중 오류 발생: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 중복 페어 조회: 경로와 베이스명으로 tif/tfw 후보 반환
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public List<FileDto.Basic> findDuplicatePair(String targetPath, String baseName) {
|
||||||
|
String tfwName = baseName + ".tfw";
|
||||||
|
String tifName = baseName + ".tif";
|
||||||
|
List<String> names = List.of(tfwName, tifName, baseName + ".tiff");
|
||||||
|
List<MapSheetMngFileEntity> entities =
|
||||||
|
mapSheetMngFileRepository.findByFilePathAndFileNameIn(targetPath, names);
|
||||||
|
return entities.stream()
|
||||||
|
.map(
|
||||||
|
e ->
|
||||||
|
new FileDto.Basic(
|
||||||
|
e.getFileName(),
|
||||||
|
Paths.get(e.getFilePath()).getFileName().toString(),
|
||||||
|
e.getFilePath(),
|
||||||
|
Paths.get(e.getFilePath(), e.getFileName()).toString(),
|
||||||
|
e.getFileExt(),
|
||||||
|
e.getFileSize() == null ? 0L : e.getFileSize(),
|
||||||
|
""))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 선택 삭제: ID 목록으로 삭제 수행하고 삭제된 ID 리스트 반환
|
||||||
|
@Transactional
|
||||||
|
public List<Long> deleteDuplicatesByIds(List<Long> ids) {
|
||||||
|
if (ids == null || ids.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
// 존재 확인 및 안전 삭제
|
||||||
|
List<MapSheetMngFileEntity> toDelete = mapSheetMngFileRepository.findAllById(ids);
|
||||||
|
List<Long> realIds = toDelete.stream().map(MapSheetMngFileEntity::getFileUid).collect(Collectors.toList());
|
||||||
|
mapSheetMngFileRepository.deleteAllById(realIds);
|
||||||
|
// 실제 파일도 제거 시도(실패 시 로그만)
|
||||||
|
toDelete.forEach(
|
||||||
|
e -> {
|
||||||
|
try {
|
||||||
|
Path p = Paths.get(e.getFilePath(), e.getFileName());
|
||||||
|
Files.deleteIfExists(p);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("파일 삭제 실패: {}", ex.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return realIds;
|
||||||
|
}
|
||||||
|
|
||||||
private void saveUploadMeta(Path savedPath, Long hstUid) {
|
private void saveUploadMeta(Path savedPath, Long hstUid) {
|
||||||
String fullPath = savedPath.toAbsolutePath().toString();
|
String fullPath = savedPath.toAbsolutePath().toString();
|
||||||
String fileName = savedPath.getFileName().toString();
|
String fileName = savedPath.getFileName().toString();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
|
|||||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
|
||||||
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngFileCheckerRepository;
|
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngFileCheckerRepository;
|
||||||
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngRepository;
|
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngRepository;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -58,4 +59,12 @@ public class MapSheetMngFileCheckerCoreService {
|
|||||||
public Optional<MapSheetMngHstEntity> findHstByUid(Long hstUid) {
|
public Optional<MapSheetMngHstEntity> findHstByUid(Long hstUid) {
|
||||||
return mapSheetMngRepository.findMapSheetMngHstInfo(hstUid);
|
return mapSheetMngRepository.findMapSheetMngHstInfo(hstUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateHstSyncCheckStart(Long hstUid) {
|
||||||
|
mapSheetMngRepository.updateHstSyncCheck(hstUid, null, ZonedDateTime.now(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateHstSyncCheckEnd(Long hstUid, String state) {
|
||||||
|
mapSheetMngRepository.updateHstSyncCheck(hstUid, state, null, ZonedDateTime.now());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package com.kamco.cd.kamcoback.postgres.repository.mapsheet;
|
package com.kamco.cd.kamcoback.postgres.repository.mapsheet;
|
||||||
|
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngFileEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngFileEntity;
|
||||||
|
import java.util.List;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
public interface MapSheetMngFileRepository extends JpaRepository<MapSheetMngFileEntity, Long> {
|
public interface MapSheetMngFileRepository extends JpaRepository<MapSheetMngFileEntity, Long> {
|
||||||
boolean existsByFileNameAndFilePath(String fileName, String filePath);
|
boolean existsByFileNameAndFilePath(String fileName, String filePath);
|
||||||
|
|
||||||
void deleteByFileNameAndFilePath(String fileName, String filePath);
|
void deleteByFileNameAndFilePath(String fileName, String filePath);
|
||||||
|
|
||||||
|
// 추가: 특정 경로에서 파일명 목록으로 중복 조회
|
||||||
|
List<MapSheetMngFileEntity> findByFilePathAndFileNameIn(String filePath, List<String> fileNames);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.postgres.repository.mapsheet;
|
|||||||
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
|
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
|
||||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
|
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
@@ -26,4 +27,7 @@ public interface MapSheetMngRepositoryCustom {
|
|||||||
MapSheetMngDto.@Valid ErrorSearchReq searchReq);
|
MapSheetMngDto.@Valid ErrorSearchReq searchReq);
|
||||||
|
|
||||||
void updateHstFileSizes(Long hstUid, long tifSizeBytes, long tfwSizeBytes, long totalSizeBytes);
|
void updateHstFileSizes(Long hstUid, long tifSizeBytes, long tfwSizeBytes, long totalSizeBytes);
|
||||||
|
|
||||||
|
// 동기화 점검 상태/시간 업데이트 (state/start/end 각각 null이면 기존값 유지)
|
||||||
|
void updateHstSyncCheck(Long hstUid, String state, ZonedDateTime start, ZonedDateTime end);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory;
|
|||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -354,6 +355,34 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
|
|||||||
query.executeUpdate();
|
query.executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateHstSyncCheck(
|
||||||
|
Long hstUid, String state, ZonedDateTime start, ZonedDateTime end) {
|
||||||
|
StringBuilder sql = new StringBuilder("UPDATE tb_map_sheet_mng_hst SET ");
|
||||||
|
boolean first = true;
|
||||||
|
if (state != null) {
|
||||||
|
sql.append("sync_check_state = :state");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (start != null) {
|
||||||
|
if (!first) sql.append(", ");
|
||||||
|
sql.append("sync_check_strt_dttm = :start");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (end != null) {
|
||||||
|
if (!first) sql.append(", ");
|
||||||
|
sql.append("sync_check_end_dttm = :end");
|
||||||
|
}
|
||||||
|
sql.append(" WHERE hst_uid = :uid");
|
||||||
|
|
||||||
|
Query query = (Query) em.createNativeQuery(sql.toString());
|
||||||
|
if (state != null) query.setParameter("state", state);
|
||||||
|
if (start != null) query.setParameter("start", start);
|
||||||
|
if (end != null) query.setParameter("end", end);
|
||||||
|
query.setParameter("uid", hstUid);
|
||||||
|
query.executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
private NumberExpression<Integer> rowNum() {
|
private NumberExpression<Integer> rowNum() {
|
||||||
return Expressions.numberTemplate(
|
return Expressions.numberTemplate(
|
||||||
Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate);
|
Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate);
|
||||||
|
|||||||
Reference in New Issue
Block a user