diff --git a/server/build.gradle b/server/build.gradle index d52049a..c6fc97c 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -71,6 +71,10 @@ dependencies { // monitoring implementation 'org.springframework.boot:spring-boot-starter-actuator' + // aws + implementation platform('io.awspring.cloud:spring-cloud-aws-dependencies:3.1.1') + implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3' + // test testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/server/src/main/java/com/fluffy/storage/application/StorageClient.java b/server/src/main/java/com/fluffy/storage/application/StorageClient.java new file mode 100644 index 0000000..cdf9909 --- /dev/null +++ b/server/src/main/java/com/fluffy/storage/application/StorageClient.java @@ -0,0 +1,10 @@ +package com.fluffy.storage.application; + +import org.springframework.web.multipart.MultipartFile; + +public interface StorageClient { + + String upload(MultipartFile file); + + void delete(String fileName); +} diff --git a/server/src/main/java/com/fluffy/storage/infra/AwsS3Client.java b/server/src/main/java/com/fluffy/storage/infra/AwsS3Client.java new file mode 100644 index 0000000..b36841e --- /dev/null +++ b/server/src/main/java/com/fluffy/storage/infra/AwsS3Client.java @@ -0,0 +1,67 @@ +package com.fluffy.storage.infra; + +import com.fluffy.global.exception.BadRequestException; +import com.fluffy.global.exception.NotFoundException; +import com.fluffy.storage.application.StorageClient; +import io.awspring.cloud.s3.S3Exception; +import io.awspring.cloud.s3.S3Resource; +import io.awspring.cloud.s3.S3Template; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component +@RequiredArgsConstructor +public class AwsS3Client implements StorageClient { + + private final S3Template s3Template; + + @Value("${spring.cloud.aws.s3.bucket}") + private String bucketName; + + @Override + public String upload(MultipartFile file) { + + if (file.isEmpty()) { + throw new BadRequestException("파일이 비어있습니다."); + } + + String fileName = generateFileName(file.getOriginalFilename()); + + try (InputStream is = file.getInputStream()) { + S3Resource upload = s3Template.upload(bucketName, fileName, is); + + return upload.getURL().toString(); + } catch (IOException | S3Exception e) { + throw new BadRequestException("파일 업로드에 실패했습니다.", e); + } + } + + @Override + public void delete(String fileName) { + try { + s3Template.deleteObject(bucketName, fileName); + } catch (S3Exception e) { + throw new NotFoundException("파일을 찾을 수 없습니다.", e); + } + } + + private String generateFileName(String originalFileName) { + if (originalFileName == null) { + throw new NotFoundException("파일 이름을 찾을 수 없습니다."); + } + + int extensionIndex = originalFileName.lastIndexOf("."); + + String extension = originalFileName.substring(extensionIndex); + String fileName = originalFileName.substring(0, extensionIndex); + + String now = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS").format(System.currentTimeMillis()); + + return "%s-%s%s".formatted(fileName, now, extension); + } +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 24a020b..4a7b616 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -27,6 +27,16 @@ spring: redis: host: localhost port: 6379 + cloud: + aws: + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} + region: + static: ${AWS_S3_REGION} + s3: + bucket: ${AWS_S3_BUCKET} + api-host: http://localhost:8080 client-host: http://localhost:5173 @@ -93,6 +103,15 @@ spring: redis: host: redis port: 6379 + cloud: + aws: + credentials: + access-key: ${AWS_ACCESS_KEY} + secret-key: ${AWS_SECRET_KEY} + region: + static: ${AWS_S3_REGION} + s3: + bucket: ${AWS_S3_BUCKET} api-host: https://api.fluffy.run client-host: https://www.fluffy.run diff --git a/server/src/test/resources/application-test.yml b/server/src/test/resources/application-test.yml index 57ff2f8..535e9c9 100644 --- a/server/src/test/resources/application-test.yml +++ b/server/src/test/resources/application-test.yml @@ -12,6 +12,16 @@ spring: redis: host: localhost port: 6379 + cloud: + aws: + credentials: + access-key: access-key + secret-key: secret-key + region: + static: ap-northeast-2 + s3: + bucket: bucket + api-host: http://localhost:8080 client-host: http://localhost:5173