Skip to content

Commit

Permalink
Merge pull request #70 from DSM-Repo/library
Browse files Browse the repository at this point in the history
pr: file 업로드 로직 재작성
  • Loading branch information
ori0o0p authored Aug 23, 2024
2 parents eda5a60 + 2a27de0 commit dbb46fe
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 155 deletions.
6 changes: 1 addition & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ dependencies {
testImplementation 'org.springframework.security:spring-security-test'

// AWS
final awsSdkVersion = "2.21.0"
implementation("software.amazon.awssdk:bom:$awsSdkVersion")
implementation("software.amazon.awssdk:s3-transfer-manager:$awsSdkVersion")
implementation("software.amazon.awssdk:s3:$awsSdkVersion")
implementation("software.amazon.awssdk.crt:aws-crt:0.27.3")
implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3:3.0.0'

// OpenFeign
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.0'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.whopper.application.file.impl;

import com.example.whopper.common.exception.file.PdfUploadFailedException;
import com.example.whopper.infrastructure.aws.s3.AwsS3Properties;
import io.awspring.cloud.s3.ObjectMetadata;
import io.awspring.cloud.s3.S3Operations;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

@Component
@RequiredArgsConstructor
class FileUploadService {

private final S3Operations s3Operations;
private final AwsS3Properties s3Properties;

void uploadFile(MultipartFile multipartFile, String key) {
try {
s3Operations.upload(
s3Properties.bucket(),
key,
multipartFile.getInputStream(),
ObjectMetadata.builder()
.contentType(multipartFile.getContentType())
.build()
);
} catch (Exception e) {
throw PdfUploadFailedException.EXCEPTION;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,21 @@

import com.example.whopper.application.file.usecase.ImageUseCase;
import com.example.whopper.infrastructure.aws.s3.AwsS3Properties;
import com.example.whopper.infrastructure.aws.s3.AwsS3FileType;
import com.example.whopper.domain.file.type.ImageType;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.UploadRequest;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
@RequiredArgsConstructor
public class ImageService implements ImageUseCase {
private static final Set<String> VALID_EXTENSIONS = Set.of(".jpg", ".jpeg", ".png", ".heic", ".svg", ".webp", ".gif");

private final S3TransferManager s3TransferManager;
private final AwsS3Properties awsS3Properties;
private final ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
private final FileUploadService fileUploadService;

public String saveImage(MultipartFile multipartFile, ImageType imageType) {
String originalFileName = multipartFile.getOriginalFilename();
Expand All @@ -36,7 +28,7 @@ public String saveImage(MultipartFile multipartFile, ImageType imageType) {
String key = generateFileKey(imageType);

// Upload file and return the key
uploadFile(multipartFile, key);
fileUploadService.uploadFile(multipartFile, key);

return key;
}
Expand All @@ -54,31 +46,6 @@ private String generateFileKey(ImageType imageType) {
return folder + "/" + UUID.randomUUID();
}

private void uploadFile(MultipartFile multipartFile, String key) {
try {
// InputStream을 사용하여 파일을 업로드
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(awsS3Properties.bucket())
.key(key)
.contentType(multipartFile.getContentType())
.acl(AwsS3FileType.IMAGE.getCannedAcl())
.build();

var uploadFuture = s3TransferManager.upload(UploadRequest.builder()
.putObjectRequest(putObjectRequest)
.requestBody(AsyncRequestBody.fromInputStream(multipartFile.getInputStream(), multipartFile.getSize(), executorService)) // ExecutorService 추가
.build()).completionFuture();

uploadFuture.whenComplete((result, exception) -> {
if (exception != null) {
throw new RuntimeException("파일 업로드 중 오류 발생", exception);
}
});
} catch (Exception e) {
throw new RuntimeException("파일 업로드 중 오류 발생", e);
}
}

private boolean isValidExtension(String extension) {
return VALID_EXTENSIONS.contains(extension);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,24 @@

import com.example.whopper.application.file.usecase.PdfUseCase;
import com.example.whopper.common.exception.file.ExtensionNotMatchException;
import com.example.whopper.common.exception.file.PdfUploadFailedException;
import com.example.whopper.infrastructure.aws.s3.AwsS3FileType;
import com.example.whopper.infrastructure.aws.s3.AwsS3Properties;
import io.awspring.cloud.s3.S3Operations;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.UploadRequest;

import java.io.InputStream;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
@RequiredArgsConstructor
public class PdfService implements PdfUseCase {

private final AwsS3Properties awsS3Properties;
private final S3TransferManager s3TransferManager;
private final S3Presigner s3Presigner;

private final ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
private final S3Operations s3Operations;
private final FileUploadService fileUploadService;

@Override
public String savePdf(MultipartFile multipartFile) {
Expand All @@ -45,47 +32,14 @@ public String savePdf(MultipartFile multipartFile) {
String date = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
String key = folder + date + "-" + UUID.randomUUID() + ".pdf";

uploadFile(multipartFile, key);
fileUploadService.uploadFile(multipartFile, key);

return key;
}

@Override
public String getPdfFileUrl(String filePath) {
GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofHours(4))
.getObjectRequest(GetObjectRequest.builder()
.bucket(awsS3Properties.bucket())
.key(filePath)
.build())
.build();

return s3Presigner.presignGetObject(getObjectPresignRequest).url().toString();
}

private void uploadFile(MultipartFile multipartFile, String key) {
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(awsS3Properties.bucket())
.key(key)
.acl(AwsS3FileType.PDF.getCannedAcl())
.build();

// MultipartFile의 InputStream을 사용하여 파일을 S3에 업로드
try (InputStream inputStream = multipartFile.getInputStream()) {
// S3 업로드 수행
var uploadFuture = s3TransferManager.upload(UploadRequest.builder()
.putObjectRequest(putObjectRequest)
.requestBody(AsyncRequestBody.fromInputStream(inputStream, multipartFile.getSize(), executorService)) // 수정된 부분
.build()).completionFuture();

uploadFuture.whenComplete((result, exception) -> {
if (exception != null) {
throw PdfUploadFailedException.EXCEPTION;
}
});
} catch (Exception e) {
throw PdfUploadFailedException.EXCEPTION;
}
return s3Operations.createSignedGetURL(awsS3Properties.bucket(), filePath, Duration.ofHours(4)).toString();
}

private String getExtension(String filename) {
Expand Down

This file was deleted.

This file was deleted.

14 changes: 10 additions & 4 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ spring:
max-file-size: 100MB
max-request-size: 100MB

cloud:
aws:
credentials:
access-key: ${AWS_ACCESS_KEY_ID}
secret-key: ${AWS_SECRET_ACCESS_KEY}
s3:
bucket: ${AWS_S3_BUCKET}
region:
static: ${AWS_REGION}

jwt:
header: Authorization
prefix: Bearer
Expand All @@ -31,10 +41,6 @@ redis:
port: 6379

aws:
region: ${AWS_REGION}
credentials:
access-key: ${AWS_ACCESS_KEY_ID}
secret-key: ${AWS_SECRET_ACCESS_KEY}
s3:
url: ${AWS_S3_URL}
bucket: ${AWS_S3_BUCKET}
Expand Down

0 comments on commit dbb46fe

Please sign in to comment.