23.03.05 S3 이용한 이미지 업로드

Kuno17·2023년 3월 4일
0

TIL/WIL

목록 보기
22/38
post-thumbnail

S3를 이용한 파일 업로드

미니프로젝트와 클론프로젝트에서 모두 유용하게 사용되는 S3 버킷을 이용한 사진 업로드 API 구현.

https://giron.tistory.com/55 S3생성 및 IAM계정 설정 참조

단!

이부분은 활성화 함으로 선택해주자 안그러면 에러를 만날 수 있다.

참조 사이트를 통해서 버킷생성과 IAM계정 설정까지만 마친 후
다음 절차를 따르자! 오늘을 기준으로 각종 오류를 만나면서 변경된점들을 반영한 코드이다....

DI 추가

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

application.yml

입력해야할 부분을 잘 확인하고 작성하자.

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB
  datasource:
    username: 사용 데이터베이스의 username 입력
    url: 사용 데이터베이스의 url 입력
    password: ''
  h2:
    console:
      enabled: 'true'

  thymeleaf:
    cache: 'false'
  jpa:
    properties:
      hibernate:
        format_sql: 'true'
        show_sql: 'true'
    hibernate:
      ddl-auto: update

jwt:
  secret:
    key: 토큰 키 값 

cloud:
  aws:
    credentials:
      access-key: 발급받은 access-key 반드시 '' 안에 입력 -> 'ssdasd'
      secret-key: 발급받은 secret-key 반드시 '' 안에 입력 -> 'ssdasd'
    region:
      static: 'ap-northeast-2' 
    s3:
     bucket: '버킷이름'
    stack:
      auto: false

logging:
  level:
    com:
      amazonaws:
        util:
          EC2MetadataUtils: error

S3Uploader.java

나는 서비스 항목에 그냥 추가했다.. 개인적으로 생각한 주석을 함께 추가.

@Slf4j
@RequiredArgsConstructor
@Component
public class S3Uploader {

    private final AmazonS3Client amazonS3Client;

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

    public String upload(MultipartFile multipartFile) throws IOException {
        //MultipartFile을 전달 받고
        //S3에 Multipartfile 타입은 전송이 안됩니다.
        File uploadFile = convert(multipartFile)
                .orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File로 전환이 실패했습니다."));

        return upload(uploadFile);
    }

    private String upload(File uploadFile) {
        String fileName = "static" + "/" + uploadFile.getName();
        String uploadImageUrl = putS3(uploadFile, fileName);
        removeNewFile(uploadFile);
        return uploadImageUrl;
    }

    //    전환된 File을 S3에 public 읽기 권한으로 put
//    외부에서 정적 파일을 읽을 수 있도록 하기 위함입니다.
    private String putS3(File uploadFile, String fileName) {
        amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile).withCannedAcl(CannedAccessControlList.PublicRead));
        return amazonS3Client.getUrl(bucket, fileName).toString();
    }

    //    로컬에 생성된 File 삭제
//    Multipartfile -> File로 전환되면서 로컬에 파일 생성된것을 삭제합니다.
    private void removeNewFile(File targetFile) {
        if (targetFile.delete()) {
            log.info("파일이 삭제되었습니다.");
        } else {
            log.info("파일이 삭제되지 못했습니다.");
        }
    }

    private Optional<File> convert(MultipartFile file) throws IOException {
        File convertFile = new File(Objects.requireNonNull(file.getOriginalFilename()));//파일이 있나없나 검사!
        if(convertFile.createNewFile()) {//createNewFile로 새로운 파일을 만들어라
            try (FileOutputStream fos = new FileOutputStream(convertFile)) { //convertFile를 OutputStream으로 만들어라
                fos.write(file.getBytes());//fos 내부의 바이트 타입의 데이터를 가져와서 저장
            }
            return Optional.of(convertFile); //Null인지 아닌지 판별
        }
        return Optional.empty(); //빈 객체를 반환?
    }
}

Controller

이부분은 구현하고자하는 방식에 따라 다르게 구현할 수 있으나 필자읙 경우 ModelAttribute를 선택했다.

   @PostMapping("/pins/create")
    public MessageResponseDto create(@ModelAttribute PinRequestDto requestDto,@AuthenticationPrincipal UserDetailsImpl userDetails)throws IOException{
        return pinService.create(userDetails.getUser(),requestDto);
    }
profile
자바 스터디 정리 - 하단 홈 버튼 참조.

0개의 댓글