diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/CardViewController.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/CardViewController.java index 36a4769227..e1ee2aef07 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/CardViewController.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/controller/CardViewController.java @@ -5,6 +5,7 @@ import com.moment.core.dto.request.CardViewRequestDTO; import com.moment.core.dto.response.CardViewResponseDTO; import com.moment.core.service.CardViewService; +import com.moment.core.service.ImageFileService; import com.moment.core.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -20,6 +21,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.List; @Slf4j @@ -29,6 +31,7 @@ public class CardViewController { private final CardViewService cardViewService; private final UserService userService; + private final ImageFileService imageFileService; // 녹음본 업로드 @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @@ -125,5 +128,17 @@ public ResponseEntity> getLikeCa CardViewResponseDTO.GetAllCardView allCardView = cardViewService.getLikeCardView(userId); return ResponseEntity.ok(APIResponse.of(SuccessCode.SELECT_SUCCESS, allCardView)); } + + // 카드뷰에 이미지 파일 저장 + @PostMapping(value = "/image/{cardViewId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity uploadImage( + @RequestHeader Long userId, + @PathVariable Long cardViewId, + @RequestPart List images + ) throws IOException { + userService.validateUserWithCardView(userId, cardViewId); + imageFileService.uploadAll(images, cardViewId, userId); + return ResponseEntity.ok(APIResponse.of(SuccessCode.INSERT_SUCCESS)); + } } diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/dto/request/CardViewRequestDTO.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/dto/request/CardViewRequestDTO.java index fa5f6aa481..db8ef4ec91 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/dto/request/CardViewRequestDTO.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/dto/request/CardViewRequestDTO.java @@ -50,4 +50,5 @@ public static class UpdateRecord { @Schema(description = "STT") private final String stt; } + } diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/service/ImageFileService.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/service/ImageFileService.java index 4d35fbc056..92a800767f 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/service/ImageFileService.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/service/ImageFileService.java @@ -1,25 +1,51 @@ package com.moment.core.service; import com.moment.core.domain.cardView.CardView; +import com.moment.core.domain.cardView.CardViewRepository; import com.moment.core.domain.imageFile.ImageFile; import com.moment.core.domain.imageFile.ImageFileRepository; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.List; +import java.util.UUID; @Service @RequiredArgsConstructor @Slf4j public class ImageFileService { private final ImageFileRepository imageFileRepository; + private final S3Service s3Service; + private final CardViewRepository cardViewRepository; @Transactional public void deleteAll(CardView cardView) { List imageFiles = imageFileRepository.findAllByCardView(cardView); + for (ImageFile imageFile : imageFiles) { + s3Service.deleteFile(imageFile.getFileName()); + } imageFiles.forEach(imageFileRepository::delete); } + @Transactional + public void uploadAll(List imageFiles, Long cardViewId, Long userId) throws IOException { + for (MultipartFile imageFile : imageFiles) { + CardView cv = cardViewRepository.findById(cardViewId).orElseThrow(() -> new IllegalArgumentException("해당 카드뷰가 없습니다.")); + String filename = UUID.randomUUID().toString(); + String url = s3Service.uploadFile(imageFile, userId, filename, false); + ImageFile image = ImageFile.builder() + .fileUrl(url) + .fileName(filename) + .cardView(cv) + .build(); + imageFileRepository.save(image); + } + + } + } diff --git a/backend/moment/moment-server/core/src/main/java/com/moment/core/service/S3Service.java b/backend/moment/moment-server/core/src/main/java/com/moment/core/service/S3Service.java index a73e2b72fc..0eff7dce8d 100644 --- a/backend/moment/moment-server/core/src/main/java/com/moment/core/service/S3Service.java +++ b/backend/moment/moment-server/core/src/main/java/com/moment/core/service/S3Service.java @@ -27,6 +27,7 @@ public class S3Service { @Value("${cloud.aws.s3.bucket}") private String bucket; + private final String s3folderPath = "users/"; public String uploadFile(MultipartFile image, Long userId, String fileName, boolean isRecord) throws IOException { this.validateImageFileExtention(image.getOriginalFilename()); @@ -37,7 +38,7 @@ public String uploadFile(MultipartFile image, Long userId, String fileName, bool } } public String uploadToS3(MultipartFile image, Long userId, String fileName, boolean isRecord) throws IOException { - String s3FileName = "users/" + userId.toString() + "/" + fileName; //S3에 저장될 파일 명 + String s3FileName = s3folderPath + userId.toString() + "/" + fileName; //S3에 저장될 파일 명 String extention = Objects.requireNonNull(image.getOriginalFilename()).substring(image.getOriginalFilename().lastIndexOf(".")); InputStream is = image.getInputStream(); @@ -58,7 +59,7 @@ public String uploadToS3(MultipartFile image, Long userId, String fileName, bool //S3로 putObject 할 때 사용할 요청 객체 //생성자 : bucket 이름, 파일 명, byteInputStream, metadata PutObjectRequest putObjectRequest = - new PutObjectRequest(bucket, s3FileName + extention, byteArrayInputStream, metadata) + new PutObjectRequest(bucket, s3FileName, byteArrayInputStream, metadata) .withCannedAcl(CannedAccessControlList.PublicRead); //실제로 S3에 이미지 데이터를 넣는 부분이다. @@ -87,7 +88,7 @@ public ResponseEntity downloadImage(String originalFilename) { } public void deleteFile(String originalFilename) { - amazonS3.deleteObject(bucket, originalFilename); + amazonS3.deleteObject(bucket, s3folderPath + originalFilename); } public void createFolder(String folderName) { diff --git a/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/controller/RootController.java b/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/controller/RootController.java index 3fb9e5e86c..610da8d58f 100644 --- a/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/controller/RootController.java +++ b/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/controller/RootController.java @@ -27,7 +27,7 @@ public ResponseEntity healthCheck() { @PostMapping("/turn-on/ec2") public ResponseEntity turnOn() { - awsService.turnOnOrOff("moment-ai", true); + awsService.turnOnOrOff("moment-ai-t4", true); return ResponseEntity.ok("EC2 is turned on"); } diff --git a/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/AwsService.java b/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/AwsService.java index 02ea7e8115..44bd2ae073 100644 --- a/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/AwsService.java +++ b/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/AwsService.java @@ -1,27 +1,33 @@ package com.moment.scheduler.service; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.http.*; import org.springframework.web.client.RestTemplate; +import java.util.LinkedHashMap; +import java.util.Map; + +@Slf4j @Service public class AwsService { String path = "https://vttrz7x4quryall56hmpfabps40mwauu.lambda-url.ap-northeast-2.on.aws/"; public void turnOnOrOff(String instanceName, boolean isStart) { // path+"start-ec2" Post 로 요청 - MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("instance_name", instanceName); + Map params = new LinkedHashMap<>(); + params.put("instance_name", instanceName); HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); // request body 생성 + HttpEntity> entity = new HttpEntity<>(params, headers); + // timeout 설정 - HttpEntity> entity = new HttpEntity<>(params, headers); RestTemplate rt = new RestTemplate(); String url = isStart ? path + "start-ec2" : path + "stop-ec2"; @@ -58,6 +64,7 @@ public Boolean isEc2Running() { if(response.getStatusCode() != HttpStatus.OK) { throw new RuntimeException("AWS 서버에 요청에 실패했습니다."); } + log.info("isEc2Running : " + response.getBody()); return response.getBody().equals("true"); } } diff --git a/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/CardViewService.java b/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/CardViewService.java index faa41ec5fc..b44ea701e4 100644 --- a/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/CardViewService.java +++ b/backend/moment/moment-server/scheduler/src/main/java/com/moment/scheduler/service/CardViewService.java @@ -35,13 +35,15 @@ public class CardViewService { public SchedulerResponseDTO.AIModelRunResponseDTO getIncompleteCardViews() throws InterruptedException { // ec2가 켜져있는지 확인 -// if (awsService.isEc2Running()){ -// throw new RuntimeException("EC2 is already running"); -// } -// awsService.turnOnOrOff("moment-ai", true); -// while (!awsService.isEc2Running()){ -// sleep(3000); -// } + if (awsService.isEc2Running()){ + throw new RuntimeException("EC2 is already running"); + } + awsService.turnOnOrOff("moment-ai-t4", true); + log.info("EC2 trying to turn on"); + while (!awsService.isEc2Running()){ + log.info("sleep"); + sleep(9000); + } // 경과 시간 체크를 위한 시작 시간 long startTime = System.currentTimeMillis(); List cards = cardViewRepository.findAllByRecordFileStatusIn(List.of("WAIT", "FAIL")); @@ -90,10 +92,10 @@ public SchedulerResponseDTO.AIModelRunResponseDTO getIncompleteCardViews() throw } long endTime = System.currentTimeMillis(); log.info("AI model run time : " + (endTime - startTime) + "ms"); -// awsService.turnOnOrOff("moment-ai", false); -// while (awsService.isEc2Running()){ -// sleep(3000); -// } + awsService.turnOnOrOff("moment-ai-t4", false); + while (awsService.isEc2Running()){ + sleep(5000); + } return SchedulerResponseDTO.AIModelRunResponseDTO.builder() .failRecordNum(failRecordNum) .successRecordNum(successRecordNum)