[S3] 파일 업로드 & 삭제

JiMin LEE·2022년 11월 25일
0
  1. build.gradle에 추가하기
  implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'


2. application.yml에 추가하기

  cloud:
    aws:
      s3:
        bucket: {버킷이름}
      credentials:
        access-key: ???
        secret-key: ???
      region:
        static: ap-northeast-2
        auto: false
      stack:
        auto: false


3. Config

  • AWSS3Config

    ```java
    package jpabook.jpashop;
    
    import com.amazonaws.auth.AWSStaticCredentialsProvider;
    import com.amazonaws.auth.BasicAWSCredentials;
    import com.amazonaws.services.s3.AmazonS3Client;
    import com.amazonaws.services.s3.AmazonS3ClientBuilder;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @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 amazonS3Client() {
            BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
            return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                    .withRegion(region)
                    .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
                    .build();
        }
    }
    ```
    1. Controller
  • AmazonS3Controller

    ```java
    package jpabook.jpashop.controller;
    
    import jpabook.jpashop.Service.AWSS3Service;
    import lombok.RequiredArgsConstructor;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.util.List;
    
    @RestController
    @RequiredArgsConstructor
    @RequestMapping("/s3")
    public class AmazonS3Controller {
    
        private final AWSS3Service awsS3Service;
    
        /**
         * Amazon S3에 파일 업로드
         * @return 성공 시 string Success 반환하게 함
         */
    //    @ApiOperation(value = "Amazon S3에 파일 업로드", notes = "Amazon S3에 파일 업로드 ")
        @PostMapping("/file")
        public String uploadFile(@RequestPart List<MultipartFile> multipartFile) {
            awsS3Service.uploadFile(multipartFile);
            return "success";
        }
    
        /**
         * Amazon S3에 업로드 된 파일을 삭제
         * @return 성공 시 string Success 반환하게 함
         */
    //    @ApiOperation(value = "Amazon S3에 업로드 된 파일을 삭제", notes = "Amazon S3에 업로드된 파일 삭제")
        @DeleteMapping("/file")
        public ResponseEntity<Void> deleteFile(@RequestParam String fileName) {
            awsS3Service.deleteFile(fileName);
            return null;
        }
    }
    ```
    1. Service
  • AWSS3Service

    package jpabook.jpashop.Service;
    
    import com.amazonaws.services.s3.AmazonS3;
    import com.amazonaws.services.s3.model.CannedAccessControlList;
    import com.amazonaws.services.s3.model.DeleteObjectRequest;
    import com.amazonaws.services.s3.model.ObjectMetadata;
    import com.amazonaws.services.s3.model.PutObjectRequest;
    import lombok.RequiredArgsConstructor;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Service;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.server.ResponseStatusException;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    @Service
    @RequiredArgsConstructor
    public class AWSS3Service {
    
        @Value("${cloud.aws.s3.bucket}")
        private String bucket;
    
        private final AmazonS3 amazonS3;
    
        public List<String> uploadFile(List<MultipartFile> multipartFile) {
            List<String> fileNameList = new ArrayList<>();
    
            // forEach 구문을 통해 multipartFile로 넘어온 파일들 하나씩 fileNameList에 추가
            multipartFile.forEach(file -> {
                String fileName = createFileName(file.getOriginalFilename());
                ObjectMetadata objectMetadata = new ObjectMetadata();
                objectMetadata.setContentLength(file.getSize());
                objectMetadata.setContentType(file.getContentType());
    
                try(InputStream inputStream = file.getInputStream()) {
                    amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
                            .withCannedAcl(CannedAccessControlList.PublicRead));
                    System.out.println("fileName = " + fileName);
                } catch(IOException e) {
                    throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드에 실패했습니다.");
                }
    
                fileNameList.add(fileName);
            });
    
            return fileNameList;
        }
    
        public void deleteFile(String fileName) {
            amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName));
        }
    
        private String createFileName(String fileName) { // 먼저 파일 업로드 시, 파일명을 난수화하기 위해 random으로 돌립니다.
            return UUID.randomUUID().toString().concat(getFileExtension(fileName));
        }
    
        private String getFileExtension(String fileName) { // file 형식이 잘못된 경우를 확인하기 위해 만들어진 로직이며, 파일 타입과 상관없이 업로드할 수 있게 하기 위해 .의 존재 유무만 판단하였습니다.
            try {
                return fileName.substring(fileName.lastIndexOf("."));
            } catch (StringIndexOutOfBoundsException e) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "잘못된 형식의 파일(" + fileName + ") 입니다.");
            }
        }
    }

결과

  • 파일 업로드


  • 파일 삭제

0개의 댓글