From cfda7d9de67d0893e6958a5fb457445b61066bd2 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Mon, 13 Oct 2025 11:49:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Feat=20:=20=ED=8C=8C=EC=9D=BC=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=EC=8B=9C=20=EC=9B=90=EB=B3=B8=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=AA=85=EC=9D=84=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/file/video/controller/VideoController.java | 4 ++-- .../back/domain/file/video/service/FileManager.java | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/back/src/main/java/com/back/domain/file/video/controller/VideoController.java b/back/src/main/java/com/back/domain/file/video/controller/VideoController.java index 4539e52d..f682c79c 100644 --- a/back/src/main/java/com/back/domain/file/video/controller/VideoController.java +++ b/back/src/main/java/com/back/domain/file/video/controller/VideoController.java @@ -19,8 +19,8 @@ public class VideoController { @GetMapping("/videos/upload") @PreAuthorize("hasRole('ADMIN')") @Operation(summary = "업로드용 URL 요청", description = "파일 업로드를 위한 Presigned URL을 발급받습니다.") - public RsData getUploadUrl() { - PresignedUrlResponse uploadUrl = fileManager.getUploadUrl(); + public RsData getUploadUrl(@RequestParam String filename) { + PresignedUrlResponse uploadUrl = fileManager.getUploadUrl(filename); UploadUrlGetResponse response = new UploadUrlGetResponse(uploadUrl.url().toString(), uploadUrl.expiresAt()); return new RsData<>("200", "업로드용 URL 요청완료", response); } diff --git a/back/src/main/java/com/back/domain/file/video/service/FileManager.java b/back/src/main/java/com/back/domain/file/video/service/FileManager.java index cbdc31ca..2b30b0d0 100644 --- a/back/src/main/java/com/back/domain/file/video/service/FileManager.java +++ b/back/src/main/java/com/back/domain/file/video/service/FileManager.java @@ -15,14 +15,21 @@ public class FileManager { private final VideoService videoService; private final S3Service s3Service; - public PresignedUrlResponse getUploadUrl() { + public PresignedUrlResponse getUploadUrl(String filename) { String uuid = UUID.randomUUID().toString(); + String ext = extractExt(filename); + String objectKey = "videos/" + uuid + "." + ext; Integer expires = 5; - URL url = s3Service.generateUploadUrl("videos/"+uuid, expires); + URL url = s3Service.generateUploadUrl(objectKey, expires); LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(expires); return new PresignedUrlResponse(url, expiresAt); } + private String extractExt(String filename) { + int pos = filename.lastIndexOf("."); + return filename.substring(pos + 1); + } + public PresignedUrlResponse getDownloadUrl(String objectKey) { Integer expires = 60; URL url = s3Service.generateDownloadUrl(objectKey, expires); From 6cd0d819670c59d62ecdcbb8b997140633391411 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Mon, 13 Oct 2025 12:45:01 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Feat=20:=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=EB=B6=80=ED=84=B0=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9E=90=EB=A5=BC=20=EC=B2=B4=ED=81=AC=ED=95=98=EA=B3=A0=20?= =?UTF-8?q?=ED=9A=8D=EB=93=9D=ED=95=98=EB=A9=B0=20URL=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=8B=9C=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../file/video/service/FileManager.java | 26 +++++++++++++++++-- .../domain/file/video/service/S3Service.java | 7 ++--- .../domain/file/service/S3ServiceTest.java | 4 +-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/back/src/main/java/com/back/domain/file/video/service/FileManager.java b/back/src/main/java/com/back/domain/file/video/service/FileManager.java index 2b30b0d0..50010938 100644 --- a/back/src/main/java/com/back/domain/file/video/service/FileManager.java +++ b/back/src/main/java/com/back/domain/file/video/service/FileManager.java @@ -2,6 +2,7 @@ import com.back.domain.file.video.dto.service.PresignedUrlResponse; +import com.back.global.exception.ServiceException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,11 +17,12 @@ public class FileManager { private final S3Service s3Service; public PresignedUrlResponse getUploadUrl(String filename) { - String uuid = UUID.randomUUID().toString(); + String contentType = validateAndGetContentType(filename); String ext = extractExt(filename); + String uuid = UUID.randomUUID().toString(); String objectKey = "videos/" + uuid + "." + ext; Integer expires = 5; - URL url = s3Service.generateUploadUrl(objectKey, expires); + URL url = s3Service.generateUploadUrl(objectKey, expires, contentType); LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(expires); return new PresignedUrlResponse(url, expiresAt); } @@ -30,6 +32,26 @@ private String extractExt(String filename) { return filename.substring(pos + 1); } + private String validateAndGetContentType(String filename) { + String ext = extractExt(filename).toLowerCase(); + switch (ext) { + case "mp4": + return "video/mp4"; + case "mov": + return "video/quicktime"; + case "avi": + return "video/x-msvideo"; + case "wmv": + return "video/x-ms-wmv"; + case "mkv": + return "video/x-matroska"; + case "webm": + return "video/webm"; + default: + throw new ServiceException("400", "지원하지 않는 동영상 파일 형식입니다: " + ext); + } + } + public PresignedUrlResponse getDownloadUrl(String objectKey) { Integer expires = 60; URL url = s3Service.generateDownloadUrl(objectKey, expires); diff --git a/back/src/main/java/com/back/domain/file/video/service/S3Service.java b/back/src/main/java/com/back/domain/file/video/service/S3Service.java index 43b4c1bb..d2aef396 100644 --- a/back/src/main/java/com/back/domain/file/video/service/S3Service.java +++ b/back/src/main/java/com/back/domain/file/video/service/S3Service.java @@ -21,12 +21,13 @@ public class S3Service { @Value("${aws.s3.bucket}") private String bucket; - public URL generateUploadUrl(String objectKey, Integer expireMinutes) { + public URL generateUploadUrl(String objectKey, Integer expireMinutes, String contentType) { validateRequest(objectKey); PutObjectRequest request = PutObjectRequest.builder() .bucket(bucket) .key(objectKey) + .contentType(contentType) .build(); PresignedPutObjectRequest presignedRequest = @@ -41,8 +42,8 @@ public URL generateUploadUrl(String objectKey, Integer expireMinutes) { return presignedRequest.url(); } - public URL generateUploadUrl(String objectKey) { - return generateUploadUrl(objectKey, 30); + public URL generateUploadUrl(String objectKey, String contentType) { + return generateUploadUrl(objectKey, 30, contentType); } public URL generateDownloadUrl(String objectKey, Integer expireMinutes) { diff --git a/back/src/test/java/com/back/domain/file/service/S3ServiceTest.java b/back/src/test/java/com/back/domain/file/service/S3ServiceTest.java index 47430cd5..acd66d2a 100644 --- a/back/src/test/java/com/back/domain/file/service/S3ServiceTest.java +++ b/back/src/test/java/com/back/domain/file/service/S3ServiceTest.java @@ -46,7 +46,7 @@ void generateUploadUrlTest() throws MalformedURLException { when(mocked.url()).thenReturn(new URL("http://localhost:8080/upload")); - URL url = s3Service.generateUploadUrl(objectKey); + URL url = s3Service.generateUploadUrl(objectKey, "video/mp4"); assertThat(url).isNotNull(); assertThat(url.toString()).isEqualTo("http://localhost:8080/upload"); @@ -77,7 +77,7 @@ void generateUploadUrl_PresignRequestNull_Test() { when(presigner.presignPutObject(any(Consumer.class))).thenReturn(null); try { - s3Service.generateUploadUrl(objectKey); + s3Service.generateUploadUrl(objectKey, "video/mp4"); } catch (Exception e) { assertThat(e).isInstanceOf(ServiceException.class); }