From 3ce8e9087c398663109cdba48a4b23cc5d680598 Mon Sep 17 00:00:00 2001 From: takoyakimchi Date: Wed, 2 Oct 2024 14:13:09 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20.jpg=20=EC=9D=B4=EC=99=B8=EC=9D=98?= =?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=8C=8C=EC=9D=BC=EB=8F=84=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friendogly/infra/S3StorageManager.java | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java b/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java index 29bd00988..9a0c86ded 100644 --- a/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java +++ b/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java @@ -27,6 +27,7 @@ @Profile("!local") public class S3StorageManager implements FileStorageManager { + private static final String IMAGE_MIME_TYPE_PREFIX = "image/"; private static final int FILE_SIZE_LIMIT = 1; private static final int MB = 1_048_576; @@ -51,37 +52,77 @@ public S3StorageManager() { @Override public String uploadFile(MultipartFile file) { - if (file == null || file.isEmpty()) { - throw new FriendoglyException("이미지 파일은 비어 있을 수 없습니다."); - } + validateNullOrEmpty(file); + validateFileSize(file); - if (file.getSize() > FILE_SIZE_LIMIT * MB) { - throw new FriendoglyException( - String.format("%dMB 미만의 사진만 업로드 가능합니다.", FILE_SIZE_LIMIT), - ErrorCode.FILE_SIZE_EXCEED, - BAD_REQUEST - ); - } + String fileName = file.getOriginalFilename(); + String contentType = file.getContentType(); + validateImageType(contentType); - // TODO: 실제 파일명에서 확장자 가져오기 - // TODO: jpg 이외의 이미지 파일도 가져올 수 있도록 수정하기 -// String fileName = file.getOriginalFilename(); - String newFilename = UUID.randomUUID() + ".jpg"; + String newFilename = generateRandomFileName(fileName); PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(BUCKET_NAME) .key(KEY_PREFIX + newFilename) - .contentType("image/jpg") + .contentType(contentType) .build(); + RequestBody requestBody = RequestBody.fromFile(convertMultiPartFileToFile(file)); + try { s3Client.putObject(putObjectRequest, requestBody); } catch (SdkException e) { throw new FriendoglyException("s3전송 과정중에 에러 발생", INTERNAL_SERVER_ERROR); } + return S3_ENDPOINT + newFilename; } + private void validateNullOrEmpty(MultipartFile file) { + if (file == null || file.isEmpty()) { + throw new FriendoglyException("이미지 파일은 비어 있을 수 없습니다."); + } + } + + private void validateFileSize(MultipartFile file) { + if (file.getSize() > FILE_SIZE_LIMIT * MB) { + throw new FriendoglyException( + String.format("%dMB 미만의 사진만 업로드 가능합니다.", FILE_SIZE_LIMIT), + ErrorCode.FILE_SIZE_EXCEED, + BAD_REQUEST + ); + } + } + + private void validateImageType(String contentType) { + if (StringUtils.isBlank(contentType)) { + throw new FriendoglyException("업로드한 파일의 Content-Type을 알 수 없습니다."); + } + + if (!contentType.startsWith(IMAGE_MIME_TYPE_PREFIX)) { + throw new FriendoglyException("이미지 파일만 업로드할 수 있습니다."); + } + } + + private String generateRandomFileName(String fileName) { + String fileExtension = parseFileExtension(fileName); + return UUID.randomUUID() + fileExtension; + } + + private String parseFileExtension(String fileName) { + if (StringUtils.isBlank(fileName)) { + throw new FriendoglyException("파일명이 비어 있습니다."); + } + + int dotIndex = fileName.lastIndexOf("."); + + if (dotIndex == -1) { + return ""; + } + + return fileName.substring(dotIndex); + } + private File convertMultiPartFileToFile(MultipartFile multipartFile) { try { File file = File.createTempFile("tmp", null); From 6b84918519652d5149ae712c2380789dfe476e0d Mon Sep 17 00:00:00 2001 From: takoyakimchi Date: Wed, 2 Oct 2024 14:18:40 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=9A=A9=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friendogly/infra/ImageTestController.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java diff --git a/backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java b/backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java new file mode 100644 index 000000000..047f02078 --- /dev/null +++ b/backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java @@ -0,0 +1,21 @@ +package com.happy.friendogly.infra; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@Profile("dev") +@RestController +@RequiredArgsConstructor +public class ImageTestController { + + private final FileStorageManager fileStorageManager; + + @PostMapping("/upload-image-test") + public String upload(@RequestParam("file") MultipartFile file) { + return fileStorageManager.uploadFile(file); + } +} From 7feb66250849924f86e4c857f716f9071a31bc09 Mon Sep 17 00:00:00 2001 From: takoyakimchi Date: Wed, 2 Oct 2024 14:24:10 +0900 Subject: [PATCH 3/5] =?UTF-8?q?remove:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=9A=A9=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friendogly/infra/ImageTestController.java | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java diff --git a/backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java b/backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java deleted file mode 100644 index 047f02078..000000000 --- a/backend/src/main/java/com/happy/friendogly/infra/ImageTestController.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.happy.friendogly.infra; - -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Profile; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; - -@Profile("dev") -@RestController -@RequiredArgsConstructor -public class ImageTestController { - - private final FileStorageManager fileStorageManager; - - @PostMapping("/upload-image-test") - public String upload(@RequestParam("file") MultipartFile file) { - return fileStorageManager.uploadFile(file); - } -} From c157dae629f4f35a98d449983ba68b375cf5f856 Mon Sep 17 00:00:00 2001 From: takoyakimchi Date: Wed, 2 Oct 2024 14:28:48 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/happy/friendogly/infra/S3StorageManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java b/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java index 9a0c86ded..5f95c2345 100644 --- a/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java +++ b/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java @@ -100,7 +100,8 @@ private void validateImageType(String contentType) { } if (!contentType.startsWith(IMAGE_MIME_TYPE_PREFIX)) { - throw new FriendoglyException("이미지 파일만 업로드할 수 있습니다."); + throw new FriendoglyException( + String.format("이미지 파일만 업로드할 수 있습니다. %s는 이미지 Content-Type이 아닙니다.", contentType)); } } From d8cd996fc58c82ad64c73382e34b02ac18c21ca1 Mon Sep 17 00:00:00 2001 From: takoyakimchi Date: Sun, 6 Oct 2024 17:55:23 +0900 Subject: [PATCH 5/5] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=A5=BC=20StringUtils.getFilenameExtension(?= =?UTF-8?q?)=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../friendogly/infra/S3StorageManager.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java b/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java index 5f95c2345..d3f48bf6d 100644 --- a/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java +++ b/backend/src/main/java/com/happy/friendogly/infra/S3StorageManager.java @@ -2,6 +2,7 @@ import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.util.StringUtils.getFilenameExtension; import com.happy.friendogly.common.ErrorCode; import com.happy.friendogly.exception.FriendoglyException; @@ -106,22 +107,13 @@ private void validateImageType(String contentType) { } private String generateRandomFileName(String fileName) { - String fileExtension = parseFileExtension(fileName); - return UUID.randomUUID() + fileExtension; - } - - private String parseFileExtension(String fileName) { - if (StringUtils.isBlank(fileName)) { - throw new FriendoglyException("파일명이 비어 있습니다."); - } + String fileExtension = getFilenameExtension(fileName); - int dotIndex = fileName.lastIndexOf("."); - - if (dotIndex == -1) { - return ""; + if (fileExtension == null) { + return UUID.randomUUID().toString(); } - return fileName.substring(dotIndex); + return UUID.randomUUID() + "." + fileExtension; } private File convertMultiPartFileToFile(MultipartFile multipartFile) {