From 6c44c47705ea49d11afb3eed752de2ff165a6fb1 Mon Sep 17 00:00:00 2001 From: bjkim Date: Thu, 18 Sep 2025 15:57:28 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=20=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(Service,=20Controller,=20Repository)=20=EB=B0=8F=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EA=B4=80=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/AttachmentController.java | 31 +++++++++- .../repository/MinioAttachmentRepository.java | 4 +- .../service/MinioAttachmentService.java | 61 +++++++++++++++++-- 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/src/main/java/kr/re/etri/autoflow/controllers/AttachmentController.java b/src/main/java/kr/re/etri/autoflow/controllers/AttachmentController.java index 2db0877..9f82339 100644 --- a/src/main/java/kr/re/etri/autoflow/controllers/AttachmentController.java +++ b/src/main/java/kr/re/etri/autoflow/controllers/AttachmentController.java @@ -3,7 +3,6 @@ package kr.re.etri.autoflow.controllers; import io.minio.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.tags.Tag; import kr.re.etri.autoflow.entity.MinioAttachmentEntity; import kr.re.etri.autoflow.payload.request.BaseSearchRequest; @@ -12,7 +11,6 @@ import kr.re.etri.autoflow.service.MinioAttachmentService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springdoc.core.annotations.ParameterObject; -import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -96,4 +94,33 @@ public class AttachmentController { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } + + @Operation(summary = "파일 업데이트", description = "파일을 새 버전으로 업로드합니다. 기존 파일은 그대로 보존되고, 버전은 +1 증가합니다.") + @PutMapping(value = "/{id}/update", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity> updateFile( + @Parameter(description = "기존 첨부파일 ID", required = true) + @PathVariable("id") Long id, + @Parameter(description = "새 파일") @RequestPart("file") MultipartFile file, + @RequestPart(value = "path", required = false) String path, + @RequestParam(value = "title", required = false) String title, + @RequestParam(value = "description", required = false) String description, + @RequestParam(value = "regUserId") String regUserId + ) { + try { + MinioAttachmentEntity updated = minioAttachmentService.updateFile( + id, file, path, title, description, regUserId + ); + + Map response = new HashMap<>(); + response.put("attachment", updated); + response.put("minioUrl", minioAttachmentService.getFileUrl(updated.getStoragePath())); + + return ResponseEntity.ok(response); + + } catch (Exception e) { + log.error("파일 업데이트 실패", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } + } \ No newline at end of file diff --git a/src/main/java/kr/re/etri/autoflow/repository/MinioAttachmentRepository.java b/src/main/java/kr/re/etri/autoflow/repository/MinioAttachmentRepository.java index 2290520..87f717a 100644 --- a/src/main/java/kr/re/etri/autoflow/repository/MinioAttachmentRepository.java +++ b/src/main/java/kr/re/etri/autoflow/repository/MinioAttachmentRepository.java @@ -6,8 +6,10 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; import java.util.List; +import java.util.Optional; @Repository public interface MinioAttachmentRepository extends JpaRepository, JpaSpecificationExecutor { - + //최신버전 파일 가져오기 + Optional findTopByRefIdAndRefTypeOrderByVersionDesc(Long refId, String refType); } diff --git a/src/main/java/kr/re/etri/autoflow/service/MinioAttachmentService.java b/src/main/java/kr/re/etri/autoflow/service/MinioAttachmentService.java index a7c86d9..0971479 100644 --- a/src/main/java/kr/re/etri/autoflow/service/MinioAttachmentService.java +++ b/src/main/java/kr/re/etri/autoflow/service/MinioAttachmentService.java @@ -91,7 +91,6 @@ public class MinioAttachmentService { /** * 전체 조회 */ - @Transactional public List findAll() { return minioAttachmentRepository.findAll(); } @@ -99,7 +98,6 @@ public class MinioAttachmentService { /** * ID 조회 */ - @Transactional public Optional findById(Long id) { return minioAttachmentRepository.findById(id); } @@ -141,10 +139,65 @@ public class MinioAttachmentService { } } + public MinioAttachmentEntity updateFile( + Long id, + MultipartFile file, + String path, + String title, + String description, + String regUserId + ) throws Exception { + // 기존 엔티티 조회 + MinioAttachmentEntity existing = minioAttachmentRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("첨부파일을 찾을 수 없습니다. ID=" + id)); + + // 최신 버전 조회 + Integer latestVersion = minioAttachmentRepository + .findTopByRefIdAndRefTypeOrderByVersionDesc(existing.getRefId(), existing.getRefType()) + .map(MinioAttachmentEntity::getVersion) + .orElse(0); + + int newVersion = latestVersion + 1; + + // 새 파일 업로드 + String storedName = UUID.randomUUID() + "-" + file.getOriginalFilename(); + String objectName = (path == null || path.isEmpty()) + ? storedName + : path + "/" + storedName; + + try (InputStream is = file.getInputStream()) { + minioClient.putObject( + PutObjectArgs.builder() + .bucket(bucketName) + .object(objectName) + .stream(is, is.available(), -1) + .contentType(file.getContentType()) + .build() + ); + } + + // 새로운 엔티티 생성 (이전 데이터는 그대로 두고, 새로운 버전 생성) + MinioAttachmentEntity newAttachment = MinioAttachmentEntity.builder() + .refId(existing.getRefId()) + .refType(existing.getRefType()) + .originalName(file.getOriginalFilename()) + .storedName(storedName) + .contentType(file.getContentType()) + .size(file.getSize()) + .storagePath(objectName) + .title(title != null ? title : existing.getTitle()) + .description(description != null ? description : existing.getDescription()) + .version(newVersion) + .regUserId(regUserId) + .build(); + + return minioAttachmentRepository.save(newAttachment); + } + + /** * 생성 (DB만 저장, 파일은 따로 업로드된 경우) */ - @Transactional public MinioAttachmentEntity create(MinioAttachmentEntity entity) { return minioAttachmentRepository.save(entity); } @@ -152,7 +205,6 @@ public class MinioAttachmentService { /** * 업데이트 */ - @Transactional public Optional update(Long id, MinioAttachmentEntity dto) { return minioAttachmentRepository.findById(id) .map(entity -> { @@ -164,7 +216,6 @@ public class MinioAttachmentService { /** * 삭제 */ - @Transactional public boolean delete(Long id) { if (!minioAttachmentRepository.existsById(id)) { return false;