From a38a8850f18f6319985953d5a7689b9378322e78 Mon Sep 17 00:00:00 2001 From: Doeun Jeong Date: Tue, 11 Mar 2025 14:24:35 +0900 Subject: [PATCH] =?UTF-8?q?fix:=2050mb=EA=B9=8C=EC=A7=80=20s3=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FileStorageService.java | 75 ++++++++++++++++--- src/main/resources/application.yml | 6 ++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/main/java/swyp_8th/bungmakase_backend/service/FileStorageService.java b/src/main/java/swyp_8th/bungmakase_backend/service/FileStorageService.java index 39b92cf..5ae4224 100644 --- a/src/main/java/swyp_8th/bungmakase_backend/service/FileStorageService.java +++ b/src/main/java/swyp_8th/bungmakase_backend/service/FileStorageService.java @@ -1,18 +1,20 @@ package swyp_8th.bungmakase_backend.service; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.DeleteObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import org.springframework.beans.factory.annotation.Value; @@ -31,19 +33,72 @@ public class FileStorageService { // 파일 업로드 및 URL 반환 public String uploadFile(MultipartFile file) { - String fileName = file.getOriginalFilename(); +// String fileName = file.getOriginalFilename(); +// +// try { +// ObjectMetadata metadata = new ObjectMetadata(); +// metadata.setContentLength(file.getSize()); // 파일 크기 설정 +// metadata.setContentType(file.getContentType()); // MIME 타입 설정 +// +// amazonS3.putObject( +// new PutObjectRequest(bucket, fileName, file.getInputStream(), metadata) // metadata 적용 +// .withCannedAcl(CannedAccessControlList.PublicRead) // 퍼블릭 읽기 권한 부여 +// ); +// +// return amazonS3.getUrl(bucket, fileName).toString(); +// } catch (IOException e) { +// throw new RuntimeException("파일 업로드 중 오류가 발생했습니다.", e); +// } try { + String fileName = file.getOriginalFilename(); + long fileSize = file.getSize(); // 파일 크기 확인 + InputStream inputStream = file.getInputStream(); + + // 파일 크기가 5MB 이하일 경우, 일반 업로드로 처리 + if (fileSize <= 5 * 1024 * 1024) { + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(fileSize); + metadata.setContentType(file.getContentType()); + + amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, metadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); // 퍼블릭 읽기 권한 부여 + + return amazonS3.getUrl(bucket, fileName).toString(); + } + + // 멀티파트 업로드 시작 ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(file.getSize()); metadata.setContentType(file.getContentType()); - amazonS3.putObject( - new PutObjectRequest(bucket, fileName, file.getInputStream(), null) - .withCannedAcl(CannedAccessControlList.PublicRead) // 퍼블릭 읽기 권한 부여 - ); + InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucket, fileName) + .withObjectMetadata(metadata); + InitiateMultipartUploadResult initResponse = amazonS3.initiateMultipartUpload(initRequest); + + byte[] buffer = new byte[5 * 1024 * 1024]; // 5MB 버퍼 + List partETags = new ArrayList<>(); + int partNumber = 1; + + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + UploadPartRequest uploadRequest = new UploadPartRequest() + .withBucketName(bucket) + .withKey(fileName) + .withUploadId(initResponse.getUploadId()) + .withPartNumber(partNumber++) + .withInputStream(new ByteArrayInputStream(buffer, 0, bytesRead)) + .withPartSize(bytesRead); + + partETags.add(amazonS3.uploadPart(uploadRequest).getPartETag()); + } + + // 업로드 완료 요청 + CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest( + bucket, fileName, initResponse.getUploadId(), partETags); + amazonS3.completeMultipartUpload(completeRequest); return amazonS3.getUrl(bucket, fileName).toString(); + } catch (IOException e) { throw new RuntimeException("파일 업로드 중 오류가 발생했습니다.", e); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index b0d2035..4a82ad3 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,10 @@ spring: + servlet: + multipart: + enabled: true + max-file-size: 50MB + max-request-size: 50MB + datasource: url: jdbc:mysql://211.188.61.117:3306/bungmakase?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&createDatabaseIfNotExist=true&autoReconnect=true username: bungmakase