AWS
스프링에서 파일을 S3(버킷)에 저장하고 반영하기
sm_hope
2022. 10. 24. 19:09
https://smhope.tistory.com/588?category=1092398
https://smhope.tistory.com/589?category=1092398
https://smhope.tistory.com/590?category=1092398
https://smhope.tistory.com/459
위 네가지를 무리없이 수행 가능하다면 쉽게 가능할 것이다.
우선 우리는 버킷을 만들고 파일을 업로드 하는것을 해 보았다.
그럼 이제 프론트에서 보여줄 차례이다.
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="">
다음과 같이 경로를 준다면 정상적으로 파일(이미지)을 뽑아오는것을 볼 수 있다.