AWS

스프링에서 파일을 S3(버킷)에 저장하고 반영하기

sm_hope 2022. 10. 24. 19:09

https://smhope.tistory.com/588?category=1092398 

 

버킷 만들기 (이미지, 동영상등을 저장)

버킷은 이미지 동영상을 저장하는 창고라고 생각하면 된다. 스프링에서 이미지나 파일을 저장할때 버킷에 넣는다. 이름은 사용하고자 하는 이름을 설정한다. 지역은 한국이니까 서울로 체크한

smhope.tistory.com

https://smhope.tistory.com/589?category=1092398 

 

사용자 만들기 (iam)

버킷을 만들었다. https://smhope.tistory.com/588 버킷 만들기 (이미지, 동영상등을 저장) 버킷은 이미지 동영상을 저장하는 창고라고 생각하면 된다. 스프링에서 이미지나 파일을 저장할때 버킷에 넣는

smhope.tistory.com

https://smhope.tistory.com/590?category=1092398 

 

REST API로 버킷에 파일 업로드 (SpringBoot 이용)

특정 URL로 들어가면 파일이 업로드 되게 만들어 보자. 1. application.yml 수정 cloud: aws: credentials: accessKey: 발급받은 엑세스 키 secretKey: 발급받은 엑세스 비밀키 s3: bucket: 작성한 버킷이름 dir:..

smhope.tistory.com

https://smhope.tistory.com/459

 

[스프링부트] 다중 파일 업로드

html mulilple로 인해 다중 파일이 업로드 가능하다. script 미리보기 또한 가능하다. Service @Service @RequiredArgsConstructor public class FileUploadService { private final FilesRepository filesReposit..

smhope.tistory.com

위 네가지를 무리없이 수행 가능하다면 쉽게 가능할 것이다.

 

우선 우리는 버킷을 만들고 파일을 업로드 하는것을 해 보았다.

그럼 이제 프론트에서 보여줄 차례이다.

 

 

 

import org.springframework.beans.factory.annotation.Value;

... 생략 ...

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

    private final AmazonS3 amazonS3;

... 생략 ...

    public void awsFileUpload(List<MultipartFile> files) throws IOException {
        files.stream()
                .forEach(file-> {
                    String s3FileName = String.valueOf(UUID.randomUUID());
                    ObjectMetadata objectMetadata = new ObjectMetadata();
                    try{
                        objectMetadata.setContentLength(file.getInputStream().available());
                        amazonS3.putObject(bucket, s3FileName, file.getInputStream(), objectMetadata);
                    }catch (IOException e){
                        throw new RuntimeException(e);
                    }
                });

    }
   
... 생략 ...

위 코드로 클라우드에 파일을 업로드 했다.

그리고, 

@Service
@RequiredArgsConstructor
public class FileUploadService {
    private final FilesRepository filesRepository;
    private final ArticleService articleService;

    @Async
    public void doUpload(ArticleWriteForm articleWriteForm, List<MultipartFile> multiFileList, HttpServletRequest request, HttpSession session) {

        String root = System.getProperty("user.dir") + "\\src\\main\\resources\\static\\uploadFiles";
        File fileCheck = new File(root);
        if (!fileCheck.exists()) fileCheck.mkdirs();

        List<Map<String, String>> fileList = new ArrayList<>();

        for (int i = 0; i < multiFileList.size(); i++) {
            String originFile = multiFileList.get(i).getOriginalFilename();
            String ext = originFile.substring(originFile.lastIndexOf("."));
            String changeFile = UUID.randomUUID().toString() + ext;

            Map<String, String> map = new HashMap<>();
            map.put("originFile", originFile);
            map.put("changeFile", changeFile);

            fileList.add(map);
        }

        try {
            for (int i = 0; i < multiFileList.size(); i++) {
                File uploadFile = new File(root + "\\" + fileList.get(i).get("changeFile"));
                multiFileList.get(i).transferTo(uploadFile);
            }
            uploadDB(fileList, session, articleWriteForm);
            System.out.println("다중 파일 업로드 성공!");

        } catch (IllegalStateException | IOException e) {
            System.out.println("다중 파일 업로드 실패 ㅠㅠ");
            for (int i = 0; i < multiFileList.size(); i++) {
                new File(root + "\\" + fileList.get(i).get("changeFile")).delete();
            }
            e.printStackTrace();
        }
    }

    private void uploadDB(List<Map<String, String>> fileName, HttpSession session, ArticleWriteForm articleWriteForm) {
    
        Article aritcle = articleService.doWrite((long) session.getAttribute("loginedUserId"), articleWriteForm.getTitle(), articleWriteForm.getBody());
        for (Map<String, String> file : fileName) {
            Files files = new Files();
            files.setFilename(file.get("changeFile"));
            files.setArticle(aritcle);
            filesRepository.save(files);

        }
    }
}

이 코드를 통해서 파일을 스토리지에 생성하고 DB에 메타데이터를 저장했다.

 

두 코드를 조합하면 버킷에 저장하면서 화면에 반영하는 환상적인 일이 일어날 것이다.

 

 

바로 해보면,

import org.springframework.beans.factory.annotation.Value;

... 생략 ...

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

    private final AmazonS3 amazonS3;

... 생략 ...

    public void awsFileUpload(List<MultipartFile> files) throws IOException {
        files.stream()
                .forEach(file-> {
                    String s3FileName = String.valueOf(UUID.randomUUID());
                    ObjectMetadata objectMetadata = new ObjectMetadata();
                    try{
                        objectMetadata.setContentLength(file.getInputStream().available());
                        amazonS3.putObject(bucket, s3FileName, file.getInputStream(), objectMetadata);
                    }catch (IOException e){
                        throw new RuntimeException(e);
                    }
                });

    }
   
... 생략 ...

이 코드로 버킷에 업로드를 하고

 

 private void uploadDB(List<Map<String, String>> fileName, HttpSession session, ArticleWriteForm articleWriteForm) {
    
        Article aritcle = articleService.doWrite((long) session.getAttribute("loginedUserId"), articleWriteForm.getTitle(), articleWriteForm.getBody());
        for (Map<String, String> file : fileName) {
            Files files = new Files();
            files.setFilename(file.get("changeFile"));
            files.setArticle(aritcle);
            filesRepository.save(files);

        }
    }

이 코드를 통해 DB에 메타데이터를 저장하면 될것이다!

 

 

import org.springframework.beans.factory.annotation.Value;

... 생략 ...

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

    private final AmazonS3 amazonS3;

... 생략 ...

    public void awsFileUpload(List<MultipartFile> files, HttpSession session, ArticleWriteForm articleWriteForm) throws IOException {
        files.stream()
                .forEach(file-> {
                    String originFile = file.getOriginalFilename();
                    String ext = originFile.substring(originFile.lastIndexOf("."));
                    String s3FileName = UUID.randomUUID().toString() + ext;                
                    ObjectMetadata objectMetadata = new ObjectMetadata();
                    try{
                        objectMetadata.setContentLength(file.getInputStream().available());                    
                        amazonS3.putObject(bucket, s3FileName, file.getInputStream(), objectMetadata);
                        uploadDB(s3FileName, session, articleWriteForm);
                    }catch (IOException e){
                        throw new RuntimeException(e);
                    }
                });
    }
    
     private void uploadDB(String fileName, HttpSession session, ArticleWriteForm articleWriteForm) {
    
        Article aritcle = articleService.doWrite((long) session.getAttribute("loginedUserId"), articleWriteForm.getTitle(), articleWriteForm.getBody());
        Files files = new Files();
        files.setFilename(fileName);
        files.setArticle(aritcle);
        filesRepository.save(files);
    }
   
... 생략 ...

이렇게 하면 확장자도 챙기고, 메타데이터에도 파일을 넣을 수 있다.

 

그러면 버킷에는

다음과 같이 파일이 들어갈 것이다!

또한 객체 개요를 보면

https://버킷이름.s3.리전.amazonaws.com/5790d114-ab6e-4542-9091-2f1700f0d118.jpg
https://버킷이름.s3.리전.amazonaws.com/8be3531f-c0aa-4391-be0c-c6411180a855.jpg

이런식으로 뒤에 UUID로 뽑은 데이터만 다르고

https://버킷이름.s3.리전.amazonaws.com/ 은 형식이 같다는것을 알수 있다.

 

따라서

# 타임리프
<img th:src="'https://버킷이름.s3.리전.amazonaws.com/'${file}", alt="">

# 리액트
<img src=`https://버킷이름.s3.리전.amazonaws.com/${file}`, alt="">

다음과 같이 경로를 준다면 정상적으로 파일(이미지)을 뽑아오는것을 볼 수 있다.