From d2203f0389794a17a082f6e71ed5450d181f82d2 Mon Sep 17 00:00:00 2001 From: kseysh Date: Fri, 5 Apr 2024 15:51:22 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20s3=20expiration=20=EC=9E=84=EC=8B=9C?= =?UTF-8?q?=EC=A1=B0=EC=B9=98=EB=A1=9C=2010=EC=8B=9C=EA=B0=84=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#240)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/app/application/s3/S3Service.java | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/sopt/app/application/s3/S3Service.java b/src/main/java/org/sopt/app/application/s3/S3Service.java index 18c89114..109e1f0f 100644 --- a/src/main/java/org/sopt/app/application/s3/S3Service.java +++ b/src/main/java/org/sopt/app/application/s3/S3Service.java @@ -5,7 +5,6 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.CannedAccessControlList; import com.amazonaws.services.s3.model.ObjectMetadata; @@ -18,11 +17,11 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; import javax.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.val; import org.joda.time.LocalDateTime; +import org.slf4j.LoggerFactory; import org.sopt.app.common.exception.BadRequestException; import org.sopt.app.common.response.ErrorCode; import org.springframework.beans.factory.annotation.Value; @@ -37,12 +36,10 @@ public class S3Service { private final ArrayList imageFileExtension = new ArrayList<>( List.of(".jpg", ".jpeg", ".png", ".JPG", ".JPEG", ".PNG")); - private final AmazonS3 s3Client; - - @Value("${cloud.aws.credentials.accesskey}") + @Value("${cloud.aws.credentials.access-key}") private String accessKey; - @Value("${cloud.aws.credentials.secretkey}") + @Value("${cloud.aws.credentials.secret-key}") private String secretKey; @Value("${cloud.aws.s3.bucket}") @@ -56,11 +53,11 @@ public class S3Service { @PostConstruct - public AmazonS3Client amazonS3Client() { - val awsCredentials = new BasicAWSCredentials(accessKey, secretKey); //accessKey 와 secretKey를 이용하여 자격증명 객체를 얻는다. - return (AmazonS3Client) AmazonS3ClientBuilder.standard() - .withRegion(region) // region 설정 - .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) // 자격증명을 통해 S3 Client를 가져온다. + public AmazonS3 getAmazonS3() { + val awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .build(); } @@ -72,29 +69,28 @@ public List uploadDeprecated(List multipartFiles) { return multipartFiles.stream().map(file -> { val fileName = createFileName(file.getOriginalFilename()); + val amazonS3 = getAmazonS3(); val objectMetadata = new ObjectMetadata(); objectMetadata.setContentLength(file.getSize()); objectMetadata.setContentType(file.getContentType()); try (InputStream inputStream = file.getInputStream()) { - s3Client.putObject( + amazonS3.putObject( new PutObjectRequest(bucket + "/mainpage/makers-app", fileName, inputStream, objectMetadata) .withCannedAcl(CannedAccessControlList.PublicRead)); - return s3Client.getUrl(bucket + "/mainpage/makers-app", fileName).toString(); + return amazonS3.getUrl(bucket + "/mainpage/makers-app", fileName).toString(); } catch (IOException e) { throw new BadRequestException("요청이 처리 되지 않았습니다."); } - }).collect(Collectors.toList()); + }).toList(); } - // 이미지파일명 중복 방지 private String createFileName(String fileName) { return UUID.randomUUID().toString().concat(getFileExtension(fileName)); } - // 파일 유효성 검사 private String getFileExtension(String fileName) { - if (fileName.length() == 0) { + if (fileName.isEmpty()) { throw new BadRequestException("유효하지 않은 파일명입니다."); } @@ -109,11 +105,13 @@ public S3Info.PreSignedUrl getPreSignedUrl(String folderName) { val now = LocalDateTime.now(); val folderURI = bucket + "/mainpage/makers-app-img/" + folderName; val randomFileName = UUID.randomUUID(); + val amazonS3 = getAmazonS3(); URI uri; try { - uri = this.s3Client.generatePresignedUrl(folderURI, - randomFileName.toString(), now.plusHours(1).toDate(), HttpMethod.PUT).toURI(); + // TODO: EC2와 자바의 시간이 UTC와 KST로 9시간이 차이나 있어 10시간을 더함, 추후 수정 필요 + uri = amazonS3.generatePresignedUrl(folderURI, + randomFileName.toString(), now.plusHours(10).toDate(), HttpMethod.PUT).toURI(); } catch (NullPointerException | URISyntaxException e) { throw new BadRequestException(ErrorCode.PRE_SIGNED_URI_ERROR.getMessage()); } @@ -131,21 +129,21 @@ public S3Info.PreSignedUrl getPreSignedUrl(String folderName) { public void deleteFiles(List fileUrls, String folderName) { val folderURI = bucket + "/mainpage/makers-app-img/" + folderName; val fileNameList = getFileNameList(fileUrls); - fileNameList.stream().forEach(file -> deleteFile(folderURI, file)); + fileNameList.forEach(file -> deleteFile(folderURI, file)); } private List getFileNameList(List fileUrls) { return fileUrls.stream().map(url -> { val fileNameSplit = url.split("/"); return fileNameSplit[fileNameSplit.length - 1]; - }).collect(Collectors.toList()); + }).toList(); } private void deleteFile(String folderURI, String fileName) { try { - s3Client.deleteObject(folderURI, fileName.replace(File.separatorChar, '/')); + this.getAmazonS3().deleteObject(folderURI, fileName.replace(File.separatorChar, '/')); } catch (AmazonServiceException e) { - System.err.println(e.getErrorMessage()); + LoggerFactory.getLogger(S3Service.class).error(e.getErrorMessage()); } } } From f2cd05f3eeaca31c7c1ee5e7da86866da4cd3d9e Mon Sep 17 00:00:00 2001 From: kseysh Date: Fri, 5 Apr 2024 19:27:26 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20s3=20test=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#240)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/sopt/app/application/s3/S3Service.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/sopt/app/application/s3/S3Service.java b/src/main/java/org/sopt/app/application/s3/S3Service.java index 109e1f0f..e5867ac1 100644 --- a/src/main/java/org/sopt/app/application/s3/S3Service.java +++ b/src/main/java/org/sopt/app/application/s3/S3Service.java @@ -51,6 +51,8 @@ public class S3Service { @Value("${cloud.aws.s3.uri}") private String baseURI; + private final AmazonS3 amazonS3; + @PostConstruct public AmazonS3 getAmazonS3() { @@ -69,7 +71,6 @@ public List uploadDeprecated(List multipartFiles) { return multipartFiles.stream().map(file -> { val fileName = createFileName(file.getOriginalFilename()); - val amazonS3 = getAmazonS3(); val objectMetadata = new ObjectMetadata(); objectMetadata.setContentLength(file.getSize()); objectMetadata.setContentType(file.getContentType()); @@ -105,7 +106,6 @@ public S3Info.PreSignedUrl getPreSignedUrl(String folderName) { val now = LocalDateTime.now(); val folderURI = bucket + "/mainpage/makers-app-img/" + folderName; val randomFileName = UUID.randomUUID(); - val amazonS3 = getAmazonS3(); URI uri; try { @@ -141,7 +141,7 @@ private List getFileNameList(List fileUrls) { private void deleteFile(String folderURI, String fileName) { try { - this.getAmazonS3().deleteObject(folderURI, fileName.replace(File.separatorChar, '/')); + amazonS3.deleteObject(folderURI, fileName.replace(File.separatorChar, '/')); } catch (AmazonServiceException e) { LoggerFactory.getLogger(S3Service.class).error(e.getErrorMessage()); }