Skip to content

Commit 402292e

Browse files
committed
feat: presigned url 이미지 업로드 방식 추가
- presigned 이미지 업로드 방식 구현 - 테스트및 검증완료
1 parent 3b7666f commit 402292e

File tree

5 files changed

+72
-4
lines changed

5 files changed

+72
-4
lines changed

src/main/java/com/somemore/global/imageupload/usecase/ImageUploadUseCase.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
public interface ImageUploadUseCase {
66
String uploadImage(ImageUploadRequestDto requestDto);
7+
String getPresignedUrl(String filename);
78
}

src/main/java/com/somemore/global/imageupload/util/ImageUploadUtils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,14 @@ private ImageUploadUtils() {
1111
}
1212

1313
public static String generateUniqueFileName(String originalFileName) {
14+
1415
String uuid = UUID.randomUUID().toString();
16+
1517
String fileExtension = extractFileExtension(originalFileName);
16-
return uuid + fileExtension;
18+
19+
String fileNameWithoutExtension = originalFileName.substring(0, originalFileName.lastIndexOf("."));
20+
21+
return uuid + "_" + fileNameWithoutExtension + fileExtension;
1722
}
1823

1924
private static String extractFileExtension(String fileName) {

src/main/java/com/somemore/global/imageupload/validator/DefaultImageUploadValidator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public void validateFileType(MultipartFile file) {
2525
}
2626
}
2727

28+
@Override
29+
public boolean isEmptyFileName(String fileName) {
30+
return fileName == null || fileName.isEmpty();
31+
}
32+
2833
@Override
2934
public boolean isEmptyFile(MultipartFile file) {
3035
return file == null || file.isEmpty();

src/main/java/com/somemore/global/imageupload/validator/ImageUploadValidator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ public interface ImageUploadValidator {
99
void validateFileType(MultipartFile file);
1010

1111
boolean isEmptyFile(MultipartFile file);
12+
13+
boolean isEmptyFileName(String fileName);
1214
}

src/test/java/com/somemore/global/imageupload/service/ImageUploadServiceTest.java

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.somemore.global.imageupload.service;
22

33
import static org.assertj.core.api.Assertions.assertThat;
4-
import static org.junit.jupiter.api.Assertions.assertNotNull;
5-
import static org.junit.jupiter.api.Assertions.assertThrows;
6-
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
import static org.junit.jupiter.api.Assertions.*;
75
import static org.mockito.BDDMockito.given;
86
import static org.mockito.Mockito.any;
97
import static org.mockito.Mockito.mock;
@@ -17,6 +15,8 @@
1715
import com.somemore.support.IntegrationTestSupport;
1816
import java.io.IOException;
1917
import java.io.InputStream;
18+
import java.net.URL;
19+
2020
import org.junit.jupiter.api.BeforeEach;
2121
import org.junit.jupiter.api.DisplayName;
2222
import org.junit.jupiter.api.Test;
@@ -28,6 +28,9 @@
2828
import software.amazon.awssdk.core.sync.RequestBody;
2929
import software.amazon.awssdk.services.s3.S3Client;
3030
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
31+
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
32+
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
33+
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
3134

3235
class ImageUploadServiceTest extends IntegrationTestSupport {
3336

@@ -99,4 +102,56 @@ void uploadImageWithEmptyFile() {
99102
// then
100103
assertThat(imgUrl).isEqualTo(ImageUploadService.DEFAULT_IMAGE_URL);
101104
}
105+
106+
@DisplayName("유효한 파일명으로 사전 서명된 URL을 생성할 수 있다.")
107+
@Test
108+
void getPresignedUrl_success() {
109+
// given
110+
String filename = "testImage.jpg";
111+
112+
// Mock the validator to return false (file name is valid)
113+
when(imageUploadValidator.isEmptyFileName(filename)).thenReturn(false);
114+
115+
// Mock the S3Presigner to return a URL
116+
S3Presigner mockPresigner = mock(S3Presigner.class);
117+
ReflectionTestUtils.setField(imageUploadService, "s3Presigner", mockPresigner);
118+
119+
PresignedGetObjectRequest mockPresignedRequest = mock(PresignedGetObjectRequest.class);
120+
URL mockUrl = mock(URL.class);
121+
122+
when(mockUrl.toString()).thenReturn("https://test-bucket.s3.amazonaws.com/unique-test-image.jpg");
123+
when(mockPresignedRequest.url()).thenReturn(mockUrl);
124+
when(mockPresigner.presignGetObject(any(GetObjectPresignRequest.class))).thenReturn(mockPresignedRequest);
125+
126+
// when
127+
String presignedUrl = imageUploadService.getPresignedUrl(filename);
128+
129+
// then
130+
assertNotNull(presignedUrl);
131+
assertTrue(presignedUrl.startsWith("https://test-bucket.s3.amazonaws.com/"));
132+
assertTrue(presignedUrl.endsWith(".jpg"));
133+
134+
// Verify interactions
135+
verify(imageUploadValidator, times(1)).isEmptyFileName(filename);
136+
verify(mockPresigner, times(1)).presignGetObject(any(GetObjectPresignRequest.class));
137+
}
138+
139+
@DisplayName("파일명 검증에 실패하면 null을 반환한다.")
140+
@Test
141+
void getPresignedUrl_invalidFileName() {
142+
143+
// given
144+
String filename = "";
145+
146+
when(imageUploadValidator.isEmptyFileName(filename)).thenReturn(true);
147+
148+
// when
149+
String presignedUrl = imageUploadService.getPresignedUrl(filename);
150+
151+
// then
152+
assertNull(presignedUrl);
153+
154+
// Verify interactions
155+
verify(imageUploadValidator, times(1)).isEmptyFileName(filename);
156+
}
102157
}

0 commit comments

Comments
 (0)