From 41f80abf2d8d6cf4d7f16901f570b13a44c1731c Mon Sep 17 00:00:00 2001 From: Jung Dayeon <102217402+al1kite@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:45:28 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat=20:=20s3=20=EB=B2=84=ED=82=B7=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?Component=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 ++ lombok.config | 1 + .../component/aws/S3UploadComponent.java | 64 +++++++++++++++++++ .../yesable_be/config/aws/S3Config.java | 36 +++++++++++ 4 files changed, 105 insertions(+) create mode 100644 lombok.config create mode 100644 src/main/java/com/example/yesable_be/component/aws/S3UploadComponent.java create mode 100644 src/main/java/com/example/yesable_be/config/aws/S3Config.java diff --git a/build.gradle b/build.gradle index dcfb069..5c635cd 100644 --- a/build.gradle +++ b/build.gradle @@ -67,6 +67,8 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' + // s3 + implementation 'com.amazonaws:aws-java-sdk-s3:1.12.763' // QueryDSL implementation "com.querydsl:querydsl-apt:${queryDslVersion}" implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta" @@ -78,6 +80,8 @@ dependencies { annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final' implementation "javax.annotation:javax.annotation-api:1.3.2" + implementation 'commons-io:commons-io:2.16.1' + } def generatedFilesBaseDir = "${projectDir}/src/generated" diff --git a/lombok.config b/lombok.config new file mode 100644 index 0000000..eb6db90 --- /dev/null +++ b/lombok.config @@ -0,0 +1 @@ +lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier \ No newline at end of file diff --git a/src/main/java/com/example/yesable_be/component/aws/S3UploadComponent.java b/src/main/java/com/example/yesable_be/component/aws/S3UploadComponent.java new file mode 100644 index 0000000..484ce00 --- /dev/null +++ b/src/main/java/com/example/yesable_be/component/aws/S3UploadComponent.java @@ -0,0 +1,64 @@ +package com.example.yesable_be.component.aws; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.apache.commons.io.IOUtils; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +@Slf4j +@RequiredArgsConstructor +@Component +public class S3UploadComponent { + + @Qualifier("amazonS3Builder") + private final AmazonS3 amazonS3; + + @Value("${aws.s3.bucket}") + private String yesableBucket; + + /** + * s3 버킷에 올라간 파일 삭제 + */ + public void deleteFile(String filePath) { + boolean isExistObject = amazonS3.doesObjectExist(yesableBucket, filePath); + if (isExistObject) { + amazonS3.deleteObject(yesableBucket, filePath); + } + } + + /** + * s3 버킷에 파일 업로드 + */ + public void uploadFile(InputStream inputStream, ObjectMetadata objectMetadata, String fileName) throws IOException { + byte[] bytes = IOUtils.toByteArray(inputStream); + objectMetadata.setContentLength(bytes.length); + objectMetadata.setCacheControl("max-age=10"); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); + + PutObjectRequest request = new PutObjectRequest(yesableBucket, fileName, byteArrayInputStream, objectMetadata).withCannedAcl(CannedAccessControlList.Private); + try { + amazonS3.putObject(request); + } catch (Exception e) { + // TODO : Error Handling + } + } + + /** + * S3 버킷 파일 경로 획득 + */ + public String getFileUrl(String fileName) { + return amazonS3.getUrl(yesableBucket, fileName).toString(); + } + + +} diff --git a/src/main/java/com/example/yesable_be/config/aws/S3Config.java b/src/main/java/com/example/yesable_be/config/aws/S3Config.java new file mode 100644 index 0000000..504e12f --- /dev/null +++ b/src/main/java/com/example/yesable_be/config/aws/S3Config.java @@ -0,0 +1,36 @@ +package com.example.yesable_be.config.aws; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +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 s3AccessKey; + @Value("${cloud.aws.credentials.secret-key}") + private String s3SecretKey; + @Value("${cloud.aws.region.static}") + private String region; + + @Bean(name = "amazonS3Builder") + public AmazonS3 amazonS3() { + + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(buildAWSStaticCredentialsProvider(s3AccessKey, s3SecretKey)) + .build(); + } + + private AWSStaticCredentialsProvider buildAWSStaticCredentialsProvider(String accessKey, String secretKey) { + AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return new AWSStaticCredentialsProvider(awsCredentials); + } + +} From 66da7045f9d341b6ca94c4c55165f240f2612949 Mon Sep 17 00:00:00 2001 From: Jung Dayeon <102217402+al1kite@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:00:53 +0900 Subject: [PATCH 2/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=20Executor=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yesable_be/constant/CommonConstants.java | 6 ++++ .../yesable_be/service/s3/UploadExecutor.java | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/main/java/com/example/yesable_be/constant/CommonConstants.java create mode 100644 src/main/java/com/example/yesable_be/service/s3/UploadExecutor.java diff --git a/src/main/java/com/example/yesable_be/constant/CommonConstants.java b/src/main/java/com/example/yesable_be/constant/CommonConstants.java new file mode 100644 index 0000000..2ee7977 --- /dev/null +++ b/src/main/java/com/example/yesable_be/constant/CommonConstants.java @@ -0,0 +1,6 @@ +package com.example.yesable_be.constant; + +public class CommonConstants { + public static final String PNG = "png"; + public static final String PNG_CONTENT_TYPE = "image/png"; +} diff --git a/src/main/java/com/example/yesable_be/service/s3/UploadExecutor.java b/src/main/java/com/example/yesable_be/service/s3/UploadExecutor.java new file mode 100644 index 0000000..821a6d6 --- /dev/null +++ b/src/main/java/com/example/yesable_be/service/s3/UploadExecutor.java @@ -0,0 +1,34 @@ +package com.example.yesable_be.service.s3; + +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.example.yesable_be.component.aws.S3UploadComponent; +import lombok.RequiredArgsConstructor; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.InputStream; + +import static com.example.yesable_be.constant.CommonConstants.*; + +@Component +@RequiredArgsConstructor +public class UploadExecutor { + private final S3UploadComponent s3UploadComponent; + private final Environment env; + + /** + * png 파일 업로드 + */ + public String pngFileUpload(InputStream file, String filePath) throws IOException { + //TODO : exception handling 처리 후 try-catch 로 변경 + ObjectMetadata metaData = new ObjectMetadata(); + metaData.setContentType(PNG_CONTENT_TYPE); + metaData.setContentLength(file.available()); + metaData.setCacheControl("max-age=600"); + + s3UploadComponent.uploadFile(file, metaData, filePath); + return "https://" + env.getProperty("aws.s3.bucket") + "/" + filePath; + } + +}