From a5efac420a9de4f64e7b976ce8dc14adb71a20d4 Mon Sep 17 00:00:00 2001 From: bjkim Date: Wed, 17 Sep 2025 17:17:12 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=20=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EC=8B=9C=20DB=20=EB=A9=94=ED=83=80=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A0=80=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B0=8F=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autoflow/controllers/MinIOController.java | 86 ++++++++++--------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/src/main/java/kr/re/etri/autoflow/controllers/MinIOController.java b/src/main/java/kr/re/etri/autoflow/controllers/MinIOController.java index 1d7884f..f491baf 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/MinIOController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/MinIOController.java @@ -5,6 +5,9 @@ import io.minio.messages.Item; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.transaction.Transactional; +import kr.re.etri.autoflow.entity.FileUploadEntity; +import kr.re.etri.autoflow.repository.FileUploadRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -17,6 +20,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.UUID; @RestController @RequestMapping("/api/minio") @@ -25,6 +29,8 @@ import java.util.List; @Tag(name = "MinIO Controller", description = "MinIO 버킷/파일 관리 API") public class MinIOController { private final MinioClient minioClient; + private final FileUploadRepository fileUploadRepository; + @Value("${minio.bucket}") private String bucketName; @@ -68,8 +74,9 @@ public class MinIOController { return files; } - @Operation(summary = "파일 업로드", description = "MultipartFile을 MinIO 버킷에 업로드합니다. path를 지정하면 하위 폴더에 저장 가능합니다.") + @Operation(summary = "파일 업로드", description = "MultipartFile을 MinIO 버킷에 업로드하고 DB에 메타데이터를 저장합니다.") @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @Transactional public String uploadFile( @Parameter(description = "업로드할 파일") @RequestPart("file") MultipartFile file, @@ -77,10 +84,28 @@ public class MinIOController { @RequestPart(value = "path", required = false) String path ) { try (InputStream is = file.getInputStream()) { + // ===== 버전 (지금은 기본값 1, 필요 시 자동 증가 로직 가능) ===== + int version = 1; + + // ===== 파일명 처리 ===== + String uuid = UUID.randomUUID().toString(); + String originalName = file.getOriginalFilename(); + String extension = ""; + + if (originalName != null && originalName.contains(".")) { + extension = originalName.substring(originalName.lastIndexOf(".")); // ".yaml" + originalName = originalName.substring(0, originalName.lastIndexOf(".")); // "step1" + } + + // 최종 저장 파일명 => UUID-step1-ver.1.yaml + String storedName = String.format("%s-%s-ver.%d%s", uuid, originalName, version, extension); + + // MinIO 저장 경로 String objectName = (path == null || path.isEmpty()) - ? file.getOriginalFilename() - : path + "/" + file.getOriginalFilename(); + ? storedName + : path + "/" + storedName; + // ===== MinIO 업로드 ===== minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) @@ -90,9 +115,26 @@ public class MinIOController { .build() ); - // MinIO 경로 URL 생성 (NodePort 기반) + // MinIO 접근 URL (NodePort 기반) String minioUrl = String.format("%s/%s/%s", minioEndpoint, bucketName, objectName); + // ===== DB 저장 ===== + FileUploadEntity entity = FileUploadEntity.builder() + .refType("workflow_step") // 필요시 파라미터로 변경 가능 + .refId(1L) // 필요시 파라미터로 변경 가능 + .originalName(file.getOriginalFilename()) + .storedName(storedName) + .contentType(file.getContentType()) + .size(file.getSize()) + .storagePath(objectName) + .regUserId("admin") // 로그인 사용자 ID로 변경 가능 + .version(version) + .title(null) // 필요 시 @RequestPart 로 받도록 확장 + .description(null) // 필요 시 @RequestPart 로 받도록 확장 + .build(); + + fileUploadRepository.save(entity); + return "파일 업로드 성공: " + minioUrl; } catch (Exception e) { log.error("파일 업로드 실패", e); @@ -100,42 +142,6 @@ public class MinIOController { } } - @Operation(summary = "다중 파일 업로드", description = "MultipartFile 배열을 MinIO 버킷에 업로드합니다. path를 지정하면 하위 폴더에 저장 가능합니다.") - @PostMapping(value = "/upload-multiple", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public List uploadMultipleFiles( - @Parameter(description = "업로드할 파일들") - @RequestPart("files") MultipartFile[] files, - @Parameter(description = "저장 경로 (선택)") - @RequestPart(value = "path", required = false) String path - ) { - List uploadedUrls = new ArrayList<>(); - for (MultipartFile file : files) { - try (InputStream is = file.getInputStream()) { - String objectName = (path == null || path.isEmpty()) - ? file.getOriginalFilename() - : path + "/" + file.getOriginalFilename(); - - minioClient.putObject( - PutObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .stream(is, is.available(), -1) - .contentType(file.getContentType()) - .build() - ); - - String minioUrl = String.format("%s/%s/%s", minioEndpoint, bucketName, objectName); - uploadedUrls.add(minioUrl); - - } catch (Exception e) { - log.error("파일 업로드 실패: {}", file.getOriginalFilename(), e); - uploadedUrls.add("업로드 실패: " + file.getOriginalFilename() + " (" + e.getMessage() + ")"); - } - } - return uploadedUrls; - } - - @Operation(summary = "파일 다운로드", description = "MinIO에서 파일을 다운로드합니다.") @GetMapping("/download") public ResponseEntity downloadFile(@RequestParam String objectName) {