[Spring Boot] S3 이미지 업로드

2021. 6. 2. 11:35Spring

Spring Boot로 S3에 이미지 업로드 하기 Ver.1

의존성을 먼저 추가해주어야 합니다

// AWS S3
    compile group: 'org.springframework.cloud', name: 'spring-cloud-aws', version: '2.2.1.RELEASE', ext: 'pom'

    // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3
    implementation group: 'com.amazonaws', name: 'aws-java-sdk-s3', version: '1.11.993'

MultipartFile로 이미지 파일을 주고 받기

  • 총 3가지의 방법이 있습니다.
    • @RequestParam MultipartFile 타입 사용
    • ServletRequest or MultipartHttpServletRequest 타입 사용
    • 사용자 정의 Class 사용

저는 여기서 첫 번째 방법인 @RequestParam 을 사용하겠습니다.

  • 이유는 Controller의 요청 파라미터 타입 중 MultipartFile 타입에 해당하는 한 가지를 직접 골라서, File 데이터를 직접 다룰 수 있습니다.

들어가기전에 유의할 점!

  • MultipartFile은 프론트에서 Form 데이터로 보내주기 때문에 HTTP Header에 Content-Type으로 multipart/form-data를 넣어주셔야합니다.
    2021-06-01-10-07-45.png

Controller.java

@PostMapping("/api/boards")
    public Boards createBoards(HttpServletRequest req,
                               @RequestParam(value = "files", required = false) List<MultipartFile> files,
                               @RequestParam("title") String title,
                               @RequestParam("contents") String contents,
                               @RequestParam("price") String price)
          ...
}
  • 인자를 보시면 @RequestParam(value = "files", required = false) List files 로 되어 있습니다. 여기서 프론트에서 파일 이름은 files로 보내야 한다는 점과 사용자가 이미지 파일을 안보낼 수 도 있기 때문에 required = false로 지정하였습니다. 또한 여기서 주의 할 점은 required = false 이런식으로 해놓으면 NULL값이 들어오기 때문에 NULL 값 처리를 해주어야 합니다.
  • 그리고 현재 저의 프로젝트에서는 List로 Multipart를 받고 있지만 이거는 단일로 받던지 다중으로 받던지 선택입니다!

S3Service.java

    @Value("AKIASMHMW5M2RB6R6NFB")
    private String accessKey;

    @Value("rmXhmQbSZUoNDs+e4RbkBiLdws4PFTErfPs9I7/k")
    private String secretKey;

    @Value("clonedanggeon")
    private String bucket;

    @Value("ap-northeast-2")
    private String region;
  • 현재는 Access Key와 Secret Key의 값을 직접 넣어주고 있는데 원래는 .yml or .properties에 데이터를 넣어서 받아와야한다! 이 부분은 다음편에 설명하겠습니다 :)
    1. @Value로 S3Service 빈을 생성할 때 , 설정 파일의 S3 관련 프로퍼티 값을 매핑한다.
@PostConstruct
public void setS3Client() {
    AWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);

    s3Client = AmazonS3ClientBuilder.standard()
            .withCredentials(new AWSStaticCredentialsProvider(credentials))
            .withRegion(this.region)
            .build();
}
  • @PostContruct로, S3Service가 사용되기 이전에 AmazonS3Client 객체를 생성한다.
public String upload(MultipartFile file) throws IOException {
    String fileName = file.getOriginalFilename().replace(" ","");
    Date date_now = new Date(System.currentTimeMillis()); // 현재시간을 가져와 Date형으로 저장한다
    SimpleDateFormat fourteen_format = new SimpleDateFormat("yyyyMMddHHmmss");
    System.out.println(fourteen_format.format(date_now)); // 14자리 포멧으로 출력한다
    fileName = fourteen_format.format(date_now) + fileName;
    System.out.println(fileName);

    s3Client.putObject(new PutObjectRequest(bucket, fileName, file.getInputStream(), null)
            .withCannedAcl(CannedAccessControlList.PublicRead));
    return s3Client.getUrl(bucket, fileName).toString();
}
  • 간혹가다 파일명이 특수문자와 한글로 파일명이 된게 있기 때문에 파일명을 시간포맷으로 바꿔준다. 업로드는 S3에서 메서드를 따로 제공해주는데 코드에서 보면 putObject를 사용하면 된다
  • 업로드 시에는 파일 명과 경로는 직접 지정하는 경우와 그렇지 않은 경우를 나눠 오버로딩하고, 삭제 시에는 파일이 존재하는지 확인하기 위해서 AmazonS3Client의 doesObjectExist 메소드를 사용했다. 존재하는 파일인 경우에만 경로의 파일을 삭제한다.

'Spring' 카테고리의 다른 글

[Spring Boot] 이메일 보내기  (0) 2021.06.02
[Spring Boot] @Validation Exception 처리하기  (0) 2021.06.02
[Spring Boot]S3 버킷 생성  (0) 2021.06.02
[Spring boot] stomp를 활용해서 1:1 채팅 만들기  (3) 2021.04.25
[Spring] @Valid  (0) 2021.04.11