From c7fc83273167e837f2a020f7b389c4230dd8bc02 Mon Sep 17 00:00:00 2001 From: kyeong-hyeok Date: Sat, 21 Oct 2023 12:33:22 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20S3=20=EA=B4=80=EB=A0=A8=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapdagu/common/S3/FileService.java | 68 +++++++++++++++++++ .../com/project/mapdagu/config/S3Config.java | 33 +++++++++ .../com/project/mapdagu/error/ErrorCode.java | 2 + 3 files changed, 103 insertions(+) create mode 100644 src/main/java/com/project/mapdagu/common/S3/FileService.java create mode 100644 src/main/java/com/project/mapdagu/config/S3Config.java diff --git a/src/main/java/com/project/mapdagu/common/S3/FileService.java b/src/main/java/com/project/mapdagu/common/S3/FileService.java new file mode 100644 index 0000000..eb3bc0b --- /dev/null +++ b/src/main/java/com/project/mapdagu/common/S3/FileService.java @@ -0,0 +1,68 @@ +package com.project.mapdagu.common.S3; + +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.project.mapdagu.error.exception.custom.BusinessException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.util.UUID; + +import static com.project.mapdagu.error.ErrorCode.INVALID_FILE_UPLOAD; + +@Slf4j +@Service +@RequiredArgsConstructor +public class FileService { + + private final AmazonS3Client amazonS3Client; + + @Value("${cloud.aws.s3.bucket.name}") + private String bucketName; + + @Value("${cloud.aws.s3.bucket.url}") + private String defaultUrl; + + public String uploadFile(MultipartFile multipartFile, String imageType) { + if (multipartFile == null || multipartFile.isEmpty()) return null; + + String savedFileName = getSavedFileName(multipartFile, imageType); + ObjectMetadata metadata = new ObjectMetadata(); + + try (InputStream inputStream = multipartFile.getInputStream()) { + amazonS3Client.putObject(bucketName, savedFileName, inputStream, metadata); + } catch (IOException e) { + log.error("Failed to upload image", e); + throw new BusinessException(INVALID_FILE_UPLOAD); + } + return getResourceUrl(savedFileName); + } + + public void deleteFile(String fileUrl) { + String fileName = getFileNameFromResourceUrl(fileUrl); + amazonS3Client.deleteObject(new DeleteObjectRequest(bucketName, fileName)); + } + + private String getSavedFileName(MultipartFile multipartFile, String imageType) { + return String.format("%s/%s-%s", + imageType, getRandomUUID(), multipartFile.getOriginalFilename()); + } + + private String getRandomUUID() { + return UUID.randomUUID().toString().replace("-", ""); + } + + private String getResourceUrl(String savedFileName) { + return amazonS3Client.getResourceUrl(bucketName, savedFileName); + } + + private String getFileNameFromResourceUrl(String fileUrl) { + return fileUrl.replace(defaultUrl + "/", ""); + } +} \ No newline at end of file diff --git a/src/main/java/com/project/mapdagu/config/S3Config.java b/src/main/java/com/project/mapdagu/config/S3Config.java new file mode 100644 index 0000000..0244415 --- /dev/null +++ b/src/main/java/com/project/mapdagu/config/S3Config.java @@ -0,0 +1,33 @@ +package com.project.mapdagu.config; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class S3Config { + + @Value("${cloud.aws.credentials.access-key}") + private String accessKey; + + @Value("${cloud.aws.credentials.secret-key}") + private String secretKey; + + @Value("${cloud.aws.region.static}") + private String region; + + @Bean + public AmazonS3Client amazonS3Client() { + BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + + return (AmazonS3Client) AmazonS3ClientBuilder + .standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/project/mapdagu/error/ErrorCode.java b/src/main/java/com/project/mapdagu/error/ErrorCode.java index 5298e1a..bd70e8e 100644 --- a/src/main/java/com/project/mapdagu/error/ErrorCode.java +++ b/src/main/java/com/project/mapdagu/error/ErrorCode.java @@ -20,6 +20,8 @@ public enum ErrorCode { FRIEND_REQUEST_NOT_FOUND(NOT_FOUND, "해당 친구 요청을 찾을 수 없습니다."), FRIEND_NOT_FOUND(NOT_FOUND, "해당 회원과 친구가 아닙니다."), + + INVALID_FILE_UPLOAD(BAD_REQUEST, "파일 업로드에 실패하였습니다."), WRONG_SEARCH(BAD_REQUEST, "검색어를 입력해야 합니다."), ALREADY_EXIST_EVALUATION(BAD_REQUEST, "이미 존재하는 평가입니다."), ALREADY_LOGOUT_MEMBER(BAD_REQUEST, "이미 로그아웃한 회원입니다"),