Springboot S3 연동 및 이미지 업로드(2)

seongcheollee·2023년 12월 19일
0

Springboot build.gradle

의존성 추가

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

application.properties

cloud.aws.credentials.accessKey= 발급받은 IAM 키
cloud.aws.credentials.secretKey= 발급받은 IAM 키값
cloud.aws.s3.bucket=beatbuddy-s3-bucket= 버킷 이름
cloud.aws.region.static=ap-northeast-2 [버킷이 존재하는 리전]
cloud.aws.stack.auto=false AWS CloudFormation 자동 생성 x

S3Config 설정


@Configuration
public class S3Config {
    @Value("${cloud.aws.credentials.accessKey}")
    private String accessKey;

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

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

    @Bean
    public AmazonS3 amazonS3Client() {
        AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);

        return AmazonS3ClientBuilder
                .standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(region)
                .build();
    }

}

application.properties에서 설정한 값을 불러와 AmazonS3에 연결

S3Uploader

@Slf4j
@RequiredArgsConstructor 
@Component
@Service
public class S3Uploader {

    private final AmazonS3 amazonS3Client;
    private static final Logger logger = LoggerFactory.getLogger(S3Uploader.class);

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

    // MultipartFile을 전달받아 File로 전환한 후 S3에 업로드
    public String upload(MultipartFile multipartFile, String dirName) throws IOException {
        File uploadFile = convert(multipartFile)
                .orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File 전환 실패"));

        return upload(uploadFile, dirName);
    }
    
	// 파일 이름을 UUID로 변경
    private String generateUUIDFilename(File file) {
        String originalFilename = file.getName();
        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        String uuidFilename = java.util.UUID.randomUUID().toString() + extension;
        log.info("파일 이름 변경 : {}", uuidFilename);
        return uuidFilename;
    }
    
    private String upload(File uploadFile, String dirName) {
        String fileName = dirName + "/" + generateUUIDFilename(uploadFile);
        String uploadImageUrl = putS3(uploadFile, fileName);
        removeNewFile(uploadFile);  // 로컬에 생성된 File 삭제 (MultipartFile -> File 전환 하며 로컬에 파일 생성됨)

        return uploadImageUrl;      // 업로드된 파일의 S3 URL 주소 반환
    }
	
    // s3에 업로드
    private String putS3(File uploadFile, String fileName) {
        amazonS3Client.putObject(
                new PutObjectRequest(bucket, fileName, uploadFile)
                        .withCannedAcl(CannedAccessControlList.PublicRead)	// PublicRead 권한으로 업로드 됨
        );

        return amazonS3Client.getUrl(bucket, fileName).toString();
    }

    private void removeNewFile(File targetFile) {
        if(targetFile.delete()) {
            log.info("파일이 삭제되었습니다.");
        }else {
            log.info("파일이 삭제되지 못했습니다.");
        }
    }

	// MultipartFile -> File 로 변환
    private Optional<File> convert(MultipartFile file) {
        try {
            File convertFile = new File(file.getOriginalFilename());

            if (convertFile.createNewFile() || convertFile.isFile()) {
                try (FileOutputStream fos = new FileOutputStream(convertFile)) {
                    fos.write(file.getBytes());
                }
                return Optional.of(convertFile);
            } else {
                log.error("파일 생성에 실패했습니다. 파일이 이미 존재합니다: {}", convertFile.getName());
                return Optional.empty();
            }
        } catch (IOException e) {
            log.error("MultipartFile을 File로 변환하는데 실패했습니다.", e);
            return Optional.empty();
        }
    }

	// S3에서 파일 삭제
    public void delete(String dirName) {
        amazonS3Client.deleteObject(new DeleteObjectRequest(bucket, dirName));
        log.info("S3 bucket에서 File {} 삭제.", dirName);
    }

}

Secvice 로직에 설정

    @Autowired
    private S3Uploader s3Uploader;

해당하는 Service에 S3Uploader 의존성 주입

imageFileUrl = s3Uploader.upload(imageFile,"feed-image");

서비스 로직의 파라미터로 받은 MutilpartFile 과 bucket에 생성한 폴더명을 s3Uploader에 전송.

결과


레퍼런스

https://velog.io/@chaeri93/SpringBoot-AWS-S3%EB%A1%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C%ED%95%98%EA%B8%B0![](https://velog.velcdn.com/images/seongcheollee/post/01179370-4de6-434b-91e0-10594186a58a/image.png)

https://zzang9ha.tistory.com/358

0개의 댓글