본문 바로가기

SpringBoot

[SpringBoot] SpringBoot로 AWS S3 Bucket에 이미지 업로드

본격적으로 프로젝트에서 이미지를 S3 bucket으로 업로드 하기 위해

업로드 테스트 스크립트를 작성해 보았다.

 

1. bulid.graddle

//aws
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
implementation "com.amazonaws:aws-java-sdk-s3:1.12.395"

 

aws 관련 implementation을 추가해 주었다.

 

2. application.yml

# multipart 설정
spring.servlet.multipart.max-file-size: 10MB
spring.servlet.multipart.max-request-size: 10MB

# aws 설정
cloud:
  aws:
    credentials:
      accessKey: accessKey
      secretKey: secretKey
    region:
      static: ap-northeast-2
    stack:
      auto: false
    s3:
      bucket: airplanning-bucket

 

yml에서 multipart의 max file size와 max request size를 10 MB로 제한하였다.

기본 default는 각각 1 MB이다.

 

aws에서 사용자에 지정한 IAM accessKey와 secretKey를 값을 불러올 수 있도록 설정하였다.

실제 값은 환경변수를 통해 설정하였다. 노출되면 금전적 피해가 발생 할 수 있으니 노출에 조심하도록 하자.

 

region.static에는 s3이 띄워져 있는 region을 설정하였고, 해당 지역은 서울에 해당된다.

 

stack.auto는 false로 지정해 주어야한다.

Spring Cloud AWS는 기본적으로 서비스가 Cloud Formation 스택내에서 실행된다고 가정하기 때문에, false로 지정해 주지 않으면 No valid Instance error 가 발생한다.

 

s3.bucket은 s3 bucket 생성시 bucket 명을 입력한다.

혹, bucket내 directory에 업로드 하고 싶으면, bucketname/dir 식으로 경로를 지정해 주어도 된다.

 

<Reference>

https://antdev.tistory.com/93

 

[AWS] Spring Boot에서 AWS S3와 연계한 파일 업로드처리

이번 포스팅은 Spring Boot 환경에서 AWS S3(Simple Storage Service)를 연계하여 파일을 업로드하는것으로 직접 버킷 생성을 시작으로 Spring Application을 구현하기까지 작성하고자 합니다. 본 포스팅을 작성

antdev.tistory.com

 

3. AWSConfig

@Configuration
public class AWSConfig {

    @Value("${cloud.aws.credentials.accessKey}")
    private String iamAccessKey; // IAM Access Key

    @Value("${cloud.aws.credentials.secretKey}")
    private String iamSecretKey; // IAM Secret Key

    private String region = "ap-northeast-2"; // Bucket Region (서울)

    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(iamAccessKey, iamSecretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(basicAWSCredentials))
                .build();
    }


}

 

AWS에 접근 할 때, 어떤 IAM을 통해 접근하고, 어떤 지역에서 접근하는지를 설정하는 Configuration이다.

얻은 자격증명 객체를 이용해서 AmazonS3ClientBuilder를 통해 S3 Client를 가져온다.

 

<Reference>

https://doing7.tistory.com/45

 

[AWS] S3를 Spring에서 사용하기 - 이미지 업로드

[ 버킷 정책 설정 ] 버킷 정책 수정한다. 퍼블릭 엑세스 차단 해제를 하고, 버킷 정책을 설정하는 방법을 사용할 것이다. { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Pri

doing7.tistory.com

 

4. Controller

@RestController
@RequestMapping("/upload")
@RequiredArgsConstructor
public class FileUploadTestController {

    private final S3FileUploadTestService s3FileUploadTestService;

    @PostMapping
    public Response<String> uploadFile(@RequestPart("file") MultipartFile file) throws IOException {
        String url = s3FileUploadTestService.uploadFile(file);
        return Response.success(url);
    }
}

 

업로드할 file을 받아서 service에서 업로드를 진행하여 해당 file이 업로드된 s3의 url을 받아 return 해준다.

return된 url을 따라 접속하면, 업로드한 이미지를 확인 할 수 있다.

 

<Reference>

https://chordplaylist.tistory.com/261

 

[Spring Boot] AWS S3에 파일 업로드

IAM 사용자 생성 사용자 이름을 입력하고 다음으로 넘어갑니다. 검토 후 사용자를 생성합니다. 생성된 사용자에 들어가서 보안 자격 증명의 액세스키를 생성합니다. 체크박스에 체크 후 다음 버

chordplaylist.tistory.com

 

5. Service

@RequiredArgsConstructor
@Service
public class S3FileUploadTestService {

    private final AmazonS3Client amazonS3;

    @Value("${cloud.aws.s3.bucket}")
    private String bucketName;

    private String dir = "/test1";
    private String defaultUrl = "https://airplanning-bucket.s3.ap-northeast-2.amazonaws.com";

    public String uploadFile(MultipartFile file) throws IOException {

        String bucketDir = bucketName + dir;
        String dirUrl = defaultUrl + dir + "/";
        String fileName = generateFileName(file);

        amazonS3.putObject(bucketDir, fileName, file.getInputStream(), getObjectMetadata(file));
        return dirUrl + fileName;

    }

    private ObjectMetadata getObjectMetadata(MultipartFile file) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(file.getContentType());
        objectMetadata.setContentLength(file.getSize());
        return objectMetadata;
    }

    private String generateFileName(MultipartFile file) {
        return UUID.randomUUID().toString() + "-" + file.getOriginalFilename();
    }
}

 

getObjectMetadata

 

S3에 업로드 하기 위해 multipartfile의 사이즈와 타입을 S3에 알려주기 위해서 ObjectMetadata를 사용한다.

 

metadata로 contentLength를 설정하지 않으면 S3에 업로드는 되나, 다음과 같은 에러로그가 나온다고 한다.

: [io-8443-exec-65] c.amazonaws.services.s3.AmazonS3Client   : No content length specified for stream data.

metadata contentType을 설정하지않으면 url으로 접속시에 무조건 다운로드가 되게 된다.

하지만 contentType을 위와 같이 설정하게 되면, 바로 다운로드가 아닌 이미지 조회만도 가능하다.

 

generateFileName

 

s3에 파일을 저장할 때 이미지 파일 이름 중복 예방을 위해 UUID를 사용하였다.

UUID로 생성한 랜덤 String과 file의 originalname을 "-"로 연결하여 filename을 설정하였다.

 

uploadFile

 

bucketDir은 bucketname과 bucket안에 파일 저장을 원하는 directory name을 연결하여 지정하였다.

dirUrl은 bucket에 저장될 때 파일의 기본 url로 설정되는 defaultUrl에 directory name을 연결하여 지정하였다.

 

그 후, S3 API 메소드인 putObject를 이용하여 S3에 파일을 업로드를 하도록 하였다.

return값은 업로드된 파일을 조회할 수 있는 url으로 지정하였다.

 

<Reference>

https://doing7.tistory.com/45

 

[AWS] S3를 Spring에서 사용하기 - 이미지 업로드

[ 버킷 정책 설정 ] 버킷 정책 수정한다. 퍼블릭 엑세스 차단 해제를 하고, 버킷 정책을 설정하는 방법을 사용할 것이다. { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Pri

doing7.tistory.com

https://chordplaylist.tistory.com/261

 

[Spring Boot] AWS S3에 파일 업로드

IAM 사용자 생성 사용자 이름을 입력하고 다음으로 넘어갑니다. 검토 후 사용자를 생성합니다. 생성된 사용자에 들어가서 보안 자격 증명의 액세스키를 생성합니다. 체크박스에 체크 후 다음 버

chordplaylist.tistory.com

https://devlog-wjdrbs96.tistory.com/323

 

[Spring] Spring Boot AWS S3 사진 업로드 하는 법

Spring Boot S3 파일 업로드 하는 법 이번 글에서는 Spring으로 AWS S3에 파일 업로드 하는 글을 정리해보겠습니다.(기존에 썼던 글은 잘못되거나 부족한 점이 많아서 이번 기회에 다시 써서 정리해보려

devlog-wjdrbs96.tistory.com

 

Error

위의 설정을 하고 SpringBoot를 실행 할 때, 아래와 같은 오류가 발생한다.

InstanceMetadataServiceResourceFetcher 클래스의 readResource를 호출하면서 발생한 에러다.
서비스의 endpoint를 연결하지 못해 발생하는 에러라고 한다.


EC2의 메타데이터를 읽다가 발생하는 에러로써, EC2인스턴스가 아닌 곳에서는 의미가 없는 에러다.

spring-cloud-starter-aws 의존성 주입시 로컬환경은, aws환경이 아니기때문에 나는 에러라고 한다.

 

다만, timed out 하는동안 다음 프로세스를 진행하지 못하기 때문에 시간 지연이 발생하여 로직을 발생시키지 않도록 하는 것이 좋다.

 

아래의 구문을 vm options에 추가하여 해결이 가능하다.

-Dcom.amazonaws.sdk.disableEc2Metadata=true

 

<Reference>

https://lemontia.tistory.com/1006

 

[springboot] aws sdk 에러(SdkClientException: Failed to connect to service endpoint) 안띄우기

aws에 사용하는 애플리케이션을 연동해야할때 spring-cloud-start-aws 의 패키지를 쓰는 편인데, build.gradle을 설정하고 앱을 실행하면 다음 에러가 보인다. com.amazonaws.SdkClientException: Failed to connect to servi

lemontia.tistory.com

https://thalals.tistory.com/289

 

[Spring err] com.amazonaws.SdkClientException: Failed to connect to service endpoint 에러 -(aws 의존성 주입시 에러)

전에 만든 팀프로젝트를 보다가, 실행하자마자 나는 에러를 발견하였다. 개발당시에는 시간이 촉박해, 어플리케이션 자체 실행에는 문제가 없어 넘어갔던 부분이다. error code com.amazonaws.SdkClientEx

thalals.tistory.com

https://earth-95.tistory.com/117

 

[SpringBoot] SpringBoot를 이용한 AWS S3에 여러 파일 업로드 및 삭제 구현하기

들어가기 전에 원래는 AWS API Gateway + AWS lambda + AWS S3 방식으로 이미지 업로드 및 삭제를 구현하고자 했습니다. 이때, 일반적으로 javascript나 python을 사용하는 것으로 보았는데 해당 언어로 구현하

earth-95.tistory.com

 

<전체 Reference>

https://antdev.tistory.com/93
https://doing7.tistory.com/45
https://chordplaylist.tistory.com/261
https://devlog-wjdrbs96.tistory.com/323
https://lemontia.tistory.com/1006
https://thalals.tistory.com/289
https://earth-95.tistory.com/117