package kr.re.etri.autoflow.controllers; import kr.re.etri.autoflow.entity.MinioAttachmentEntity; import kr.re.etri.autoflow.payload.request.ProjectBaseSearchRequest; import kr.re.etri.autoflow.service.DynamicMinioAttachmentService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; @Slf4j @RestController @RequestMapping("/api/minio") @RequiredArgsConstructor public class DynamicMinioAttachmentController { private final DynamicMinioAttachmentService minioService; /** * 파일 업로드 */ @PostMapping("/upload") public ResponseEntity> uploadFile( @RequestParam MultipartFile file, @RequestParam(required = false) String path, @RequestParam Long refId, @RequestParam(defaultValue = "DATASET") String refType, @RequestParam(required = false) String title, @RequestParam(required = false) String description, @RequestParam(defaultValue = "1") Integer version, @RequestParam String regUserId, @RequestParam Long projectId, @RequestParam(defaultValue = "type1") String type ) { try { MinioAttachmentEntity attachment = minioService.uploadFile( file, path, refId, refType, title, description, version, regUserId, projectId, type ); Map response = new HashMap<>(); response.put("attachment", attachment); return ResponseEntity.ok(response); } catch (Exception e) { log.error("파일 업로드 실패", e); return ResponseEntity.internalServerError() .body(Map.of("error", e.getMessage())); } } /** * 파일 다운로드 */ @GetMapping("/download") public ResponseEntity downloadFile( @RequestParam(defaultValue = "4/9d08fa7973cf4c39a0979bb4d70c640b/artifacts/sklearn-model/model.pkl") String objectName, @RequestParam(defaultValue = "type1") String type ) { try { byte[] bytes = minioService.downloadFile(objectName, type); String encodedFileName = URLEncoder.encode(objectName, StandardCharsets.UTF_8) .replaceAll("\\+", "%20"); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFileName) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(bytes); } catch (Exception e) { log.error("파일 다운로드 실패", e); return ResponseEntity.internalServerError().build(); } } /** * YAML 텍스트 읽기 */ @GetMapping(value = "/readYamlText", produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity readYamlText( @RequestParam String objectName, @RequestParam(defaultValue = "type1") String type ) { try { String content = minioService.readYamlText(objectName, type); return ResponseEntity.ok(content); } catch (Exception e) { log.error("MinIO YAML 읽기 실패: {}", objectName, e); return ResponseEntity.internalServerError() .body("Error reading file: " + e.getMessage()); } } /** * 파일 삭제 */ @DeleteMapping("/delete") public ResponseEntity> deleteFile( @RequestParam Long id, @RequestParam(defaultValue = "type1") String type ) { boolean result = minioService.deleteFile(id, type); return ResponseEntity.ok(Map.of("deleted", result)); } /** * 전체 조회 */ @GetMapping("/list") public ResponseEntity> listAll() { List list = minioService.findAll(); return ResponseEntity.ok(list); } /** * 검색 + 페이지네이션 */ @PostMapping("/search") public ResponseEntity> search( @RequestBody ProjectBaseSearchRequest request, @RequestParam String refType, @RequestParam Integer refId ) { Page page = minioService.search(request, refType, refId); return ResponseEntity.ok(page); } }