diff --git a/src/main/java/com/demo/pteam/review/controller/ReviewController.java b/src/main/java/com/demo/pteam/review/controller/ReviewController.java index a0a70f0d..77548d12 100644 --- a/src/main/java/com/demo/pteam/review/controller/ReviewController.java +++ b/src/main/java/com/demo/pteam/review/controller/ReviewController.java @@ -106,4 +106,20 @@ public ResponseEntity> uploadReviewIma ApiResponse apiResponse = ApiResponse.success("이미지가 성공적으로 업로드되었습니다.", responseDto); return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse); } + + @DeleteMapping("/images/{imageId}") + public ResponseEntity> deleteReviewImage( + @PathVariable Long imageId, + @AuthenticationPrincipal UserDetails userDetails) { + + // TODO + // 현재 인증된 사용자 ID 가져오기 + // Long userId = ((CustomUserDetails) userDetails).getId(); + Long userId = null; + + reviewService.deleteReviewImage(imageId, userId); + + ApiResponse apiResponse = ApiResponse.success("이미지가 성공적으로 삭제되었습니다.", null); + return ResponseEntity.ok(apiResponse); + } } diff --git a/src/main/java/com/demo/pteam/review/service/ReviewService.java b/src/main/java/com/demo/pteam/review/service/ReviewService.java index 16a6d133..d7c3bf75 100644 --- a/src/main/java/com/demo/pteam/review/service/ReviewService.java +++ b/src/main/java/com/demo/pteam/review/service/ReviewService.java @@ -17,6 +17,7 @@ import com.demo.pteam.schedule.repository.entity.ScheduleEntity; import jakarta.persistence.EntityNotFoundException; 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; @@ -28,7 +29,7 @@ import java.util.List; import java.util.stream.Collectors; - +@Slf4j @Service @Transactional(readOnly = true) @RequiredArgsConstructor @@ -170,10 +171,16 @@ public void deleteReview(Long reviewId, Long userId) { throw new ApiException(ReviewErrorCode.NOT_REVIEW_OWNER); } - // 리뷰 이미지 연결 해제 List images = reviewImageRepository.findByReviewId(reviewId); - images.forEach(image -> image.updateReview(null)); + images.forEach(image -> { + try { + fileStorageService.deleteFile(image.getImageUrl()); + } catch (IOException e) { + log.error("Failed to delete image file: {}", e.getMessage()); + } + }); + reviewImageRepository.deleteAll(images); reviewRepository.delete(reviewEntity); } @@ -223,6 +230,35 @@ public ReviewImageUploadResponseDto uploadReviewImage(MultipartFile multipartFil } } + /** + * 리뷰 임시 이미지 삭제 + * @param imageId 삭제할 이미지 ID + * @param userId 현재 인증된 사용자 ID + */ + @Transactional + public void deleteReviewImage(Long imageId, Long userId) { + ReviewImageEntity imageEntity = reviewImageRepository.findById(imageId) + .orElseThrow(() -> new ApiException(ReviewErrorCode.IMAGE_NOT_FOUND)); + + if (!imageEntity.getUserId().equals(userId)) { + throw new ApiException(ReviewErrorCode.NOT_IMAGE_OWNER); + } + + if (imageEntity.getReview() != null) { + throw new ApiException(ReviewErrorCode.IMAGE_ALREADY_LINKED); + } + + // 파일 스토리지에서 삭제 + try { + fileStorageService.deleteFile(imageEntity.getImageUrl()); + } catch (IOException e) { + log.error("Failed to delete image file: {}", e.getMessage()); + } + + // DB에서 삭제 + reviewImageRepository.delete(imageEntity); + } + // 메서드