diff --git a/backend/build.gradle b/backend/build.gradle index 1d8c98563..275e8ce5a 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -44,6 +44,10 @@ dependencies { implementation 'com.amazonaws:aws-java-sdk-s3:1.12.518' testImplementation 'com.amazonaws:aws-java-sdk-s3:1.12.518' + // image + implementation 'net.coobird:thumbnailator:0.4.19' + testImplementation 'net.coobird:thumbnailator:0.4.19' + // mock web server testImplementation 'com.squareup.okhttp3:okhttp:4.0.1' testImplementation 'com.squareup.okhttp3:mockwebserver:4.0.1' diff --git a/backend/src/main/java/kr/codesquad/issuetracker/application/S3Service.java b/backend/src/main/java/kr/codesquad/issuetracker/application/S3Service.java index 231b74b5f..682ede40f 100644 --- a/backend/src/main/java/kr/codesquad/issuetracker/application/S3Service.java +++ b/backend/src/main/java/kr/codesquad/issuetracker/application/S3Service.java @@ -1,11 +1,23 @@ package kr.codesquad.issuetracker.application; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Objects; + +import javax.imageio.ImageIO; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import net.coobird.thumbnailator.Thumbnails; + import kr.codesquad.issuetracker.application.s3.S3Uploader; import kr.codesquad.issuetracker.domain.ImageFile; +import kr.codesquad.issuetracker.exception.ApplicationException; +import kr.codesquad.issuetracker.exception.ErrorCode; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @@ -20,6 +32,23 @@ public class S3Service { public String uploadImage(MultipartFile file) { ImageFile imageFile = ImageFile.from(file); + BufferedImage bufferedImage; + BufferedImage resizedImage; + try { + bufferedImage = ImageIO.read(file.getInputStream()); + if (Math.max(bufferedImage.getWidth(), bufferedImage.getHeight()) > 800) { + resizedImage = Thumbnails.of(bufferedImage) + .size(800, 800).asBufferedImage(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + ImageIO.write(resizedImage, Objects.requireNonNull(file.getContentType()).split("/")[1], output); + ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); + imageFile = new ImageFile(file.getOriginalFilename(), file.getContentType(), input, + (long)output.toByteArray().length); + } + } catch (IOException e) { + throw new ApplicationException(ErrorCode.NON_IMAGE_FILE); + } + // 버킷에 저장할 파일 이름 생성 String fileName = UPLOADED_IMAGES_DIR + imageFile.getRandomName(); return s3Uploader.uploadImageToS3(imageFile, fileName); diff --git a/backend/src/main/java/kr/codesquad/issuetracker/exception/ErrorCode.java b/backend/src/main/java/kr/codesquad/issuetracker/exception/ErrorCode.java index 9973b5a6b..b9cf0dda0 100644 --- a/backend/src/main/java/kr/codesquad/issuetracker/exception/ErrorCode.java +++ b/backend/src/main/java/kr/codesquad/issuetracker/exception/ErrorCode.java @@ -16,6 +16,7 @@ public enum ErrorCode { // File EMPTY_FILE(400, "파일이 없습니다."), FILE_INVALID(400, "파일이 유효하지 않습니다."), + NON_IMAGE_FILE(400, "이미지 파일이 아닙니다."), INVALID_FILE_EXTENSION(400, "지원하지 않는 파일 확장자입니다."), FILE_IO_EXCEPTION(500, "파일 입출력에 실패했습니다."), diff --git a/backend/src/main/java/kr/codesquad/issuetracker/infrastructure/persistence/mapper/IssueCountMapper.java b/backend/src/main/java/kr/codesquad/issuetracker/infrastructure/persistence/mapper/IssueCountMapper.java index 33c076ff2..785463f7a 100644 --- a/backend/src/main/java/kr/codesquad/issuetracker/infrastructure/persistence/mapper/IssueCountMapper.java +++ b/backend/src/main/java/kr/codesquad/issuetracker/infrastructure/persistence/mapper/IssueCountMapper.java @@ -10,8 +10,6 @@ public class IssueCountMapper { private int totalCounts; private int openCounts; + private int closedCounts; - public int getClosedCounts() { - return totalCounts - openCounts; - } } diff --git a/backend/src/main/java/kr/codesquad/issuetracker/presentation/FileController.java b/backend/src/main/java/kr/codesquad/issuetracker/presentation/FileController.java index 0e5041dfe..1e50388a1 100644 --- a/backend/src/main/java/kr/codesquad/issuetracker/presentation/FileController.java +++ b/backend/src/main/java/kr/codesquad/issuetracker/presentation/FileController.java @@ -18,11 +18,10 @@ @RestController public class FileController { - private final S3Service s3Service; + private final S3Service s3Service; - // 이미지 업로드 - @PostMapping("/images/upload") - public ResponseEntity> uploadImage(@RequestPart MultipartFile image) { - return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("fileUrl", s3Service.uploadImage(image))); - } + @PostMapping("/images/upload") + public ResponseEntity> uploadImage(@RequestPart MultipartFile image) { + return ResponseEntity.status(HttpStatus.CREATED).body(Map.of("fileUrl", s3Service.uploadImage(image))); + } } diff --git a/backend/src/main/resources/mapper/IssueMapper.xml b/backend/src/main/resources/mapper/IssueMapper.xml index 26655ca00..d092550f2 100644 --- a/backend/src/main/resources/mapper/IssueMapper.xml +++ b/backend/src/main/resources/mapper/IssueMapper.xml @@ -33,6 +33,7 @@ +