aws

Aws S3 ,이미지 업로드 , application.yml,application.properties

backend dev 2022. 10. 16.

s3버킷 생성

버킷생성 눌러주고 체크한 부분만 신경써준다!

객체 소유권 ACL 활성화 시켜야함!

버킷만들면 나오는 화면

 

나중에 ACL활성화를 시키지않았을때 나오는 오류!
밑에 퍼블릭 엑세스 차단설정도 일단 다 풀어놓는다. 필요시 원하는걸 차단

버킷생성후! 버킷클릭 -> 권한 -> 버킷정책 -> 편집 ( 버킷 ARN 복사)

-> 정책생성기

ARN 복사해주고 정책 생성기에 들어간다!
정책생성기 화면 다음과 같이 빈칸을 채워주고 순서대로 누른다!

Generate Policy 까지하면 복사할 json이 나온다!

복사해주자!

복사한걸 버킷정책에 붙여넣고 저장해주자!

 

 

IAM 사용자 생성

오른쪽위에 내 계정 누르고 ->  보안자격증명 누르고 -> 사용자 -> 사용자추가 

사용자 추가가 있는 화면

 

 

이름 만들어주고, 엑세스키로 설정하고 다음누르기

 

 

기존 정책 직접연결 선택 후 AmazonS3FullAccess 선택해준다

그리고 다음 쭉쭉 누르고 넘어가면

Access Key와 Secret access key가 주어지는데 잘 저장한다 ( csv 파일로 저장 후 구글드라이브같은곳에 저장)

 

 

 

 

의존성 추가하기 ( build.gradle에 dependency 추가)

//s3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

 

 

applciation.yml

s3와 관련된 프로퍼티값들을 설정해준다.

spring:
    servlet: # s3관련
      multipart:
        max-file-size: 20MB #파일하나의 최대크기
        max-request-size: 100MB # 전송하려는 총 파일들의 크기
        
#s3관련
cloud:
  aws:
    s3:
      bucket: 버켓이름
    credentials: #IAM 키값들
      access-key: 엑세스키값
      secret-key: 시크릿키값
    region:
      static: ap-northeast-2  # 지역
      auto: false
    stack:
      auto: false

application.properties나 새로운 properties 파일을 만들어 거기다가 설정해줘도된다.

 

application.yml과 application.properties의 차이?

application.properties

는 key-value 형식을 사용한다. (.점)을 이용하여 계층적 구조를 표시한다.

값을 지정할때 ${}를 이용하여 다른 환경변수의 값을 참조할 수 있다.

->  https://velog.io/@jduckling_1024/Value%EB%A1%9C-application.yml%EC%9D%98-%EA%B0%92-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0

여러개의 properties파일을 만들어 이름별로 환경변수를 정리할 수있다

 

application.yml

계층적으로 보여줘서 보기가 깔끔하다.

YAML은 한 파일에서 다중 profile를 정의 할 수있다. 

 

주의

application.yml과 application.properties를 동시에 사용하지않게 주의해야한다. 

properties가 yml보다 늦게 로드되어 yml에서 설정한 환경변수 설정들이 덮어씌어질 수 있기때문이다.

 

 

자세히 알아보기 ->

 

https://newwisdom.tistory.com/m/89

https://recordsoflife.tistory.com/m/434

 

 

S3 설정 등록 -> AwsS3Config.java 생성

@Configuration
public class AwsS3Config {
    @Value("${cloud.aws.credentials.access-key}")
    private String accessKey;

    @Value("${cloud.aws.credentials.secret-key}")
    private String secretKey;

    @Value("${cloud.aws.region.static}")
    private String region;

    @Bean
    public AmazonS3Client amazonS3() { //이부분은 AmazonS3Client로 수정(다른블로그 참고)
        AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                .withRegion(region)
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();
    }
}

 

Service 파일 생성

@Slf4j
@RequiredArgsConstructor
@Service
public class AwsS3Service {

    private final AmazonS3Client amazonS3Client;

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

    public List<String> uploadFileV1(List<MultipartFile> multipartFiles) throws BaseException {
      
        List<String> result = new ArrayList<>(); //저장된 s3 upload url을 저장할 변수

        for (int i = 0; i < multipartFiles.size(); i++) {
            MultipartFile current_file = multipartFiles.get(i); //파일하나씩 가져옴.

            String fileName = UUID.randomUUID().toString().substring(0,20); //파일이름은 uuid를 이용하여 랜덤으로 지정해서 넘긴다.

            ObjectMetadata objectMetadata = new ObjectMetadata(); //오브젝트메타데이터 생성
            objectMetadata.setContentType(current_file.getContentType()); //오브젝트 메타데이터에 파일의 컨텐트타입을 세팅

            objectMetadata.setContentLength(current_file.getSize()); //사이즈 설정 No content length specified for stream data를 위함.

            try (InputStream inputStream = current_file.getInputStream()) { //파일 업로드
                amazonS3Client.putObject(new PutObjectRequest(bucketName, fileName, inputStream, objectMetadata)
                        .withCannedAcl(CannedAccessControlList.PublicRead));


            } catch (IOException e) {
                throw new BaseException(FAIL_FILE_UPLOAD);
            }

            result.add(amazonS3Client.getUrl(bucketName, fileName).toString()); //url를 가져와서 리스트에 저장.

        }


        return result; //url 리스트를 리턴.
    }
}

업로드 함수를 가지고있는 Service를 구성해준다.

여러장의 이미지를 받고싶어서 List<MultipartFile>로 구성하였고 

S3에 저장될 파일이름은 UUID를 이용하여 랜덤으로 20가 되게 구성하였다.

중간에 오브젝트 메타데이터에 파일길이를 Set해주는 부분이있는데 그 부분을 까먹으면 

  • [WARN ] c.a.services.s3.AmazonS3Client:1714 - No content length specified for stream data. Stream contents will be buffered in memory and could result in out of memory errors.

이라는 오류가 발생한다.

 

오브젝트 메타데이터에 contentType, length 등을 담고

 

버킷이름,파일이름,인풋스트림(이미지), 오브젝트 메타데이터를 이용하여 업로드 해준다.

 

그 후 업로드한 이미지의 URL를 받아와 저장하고 리턴해준다.

 

 

Controller에서 업로드 사용

/**
 * S3업로드 실험용 api
 * */
@Transactional
@ResponseBody
@PostMapping("/upload")
public BaseResponse<PostUploadRes> uploadFiles (@RequestPart(value = "files")List<MultipartFile> multipartFiles)
{
    try{
        List<String> result_urls = awsS3Service.uploadFileV1(multipartFiles);
        PostUploadRes postUploadRes = new PostUploadRes(result_urls);
        return new BaseResponse<>(postUploadRes);
    }catch (BaseException e)
    {
        e.printStackTrace();
        return new BaseResponse<>(e.getStatus());
    }

}

다음과 같이 @RequestPart를 이용하여 파일을 받는다.  (s3에 저장된 url를 리턴하는 api)

 

 

 

 

 

포스트맨에서 Body에서 form-data를 선택

Key를 적는곳 오른쪽에 File로 꼭 선택해줘야한다.

 

포스트맨 테스트 화면

 

 

s3에서 잘 저장되어있는걸 확인할 수 있음

 

파일명에 관해서 다른걸 추가하고 싶다면 또는 파일다운로드 관련

참고 블로그 확인

 

 

 

참고 + 추가적인내용

https://www.sunny-son.space/spring/Springboot%EB%A1%9C%20S3%20%ED%8C%8C%EC%9D%BC%20%EC%97%85%EB%A1%9C%EB%93%9C/

 

Springboot로 S3 파일 업로드하기

이번 포스팅은 스프링에서 AWS S3 파일 업로드하는 방법입니다. 주로 이미지 파일을 올릴 때 많이 사용되곤 합니다. 1. 의존성 추가하기 build.gradle awspring/spring-cloud-aws Spring-Cloud-AWS 의존성을 추가합

www.sunny-son.space

 

'aws' 카테고리의 다른 글

인텔리제이 - ec2연결 (remote host)  (0) 2022.10.09

댓글