이전 포스팅에서 사진 업로드 및 삭제를 구현하고 서버에 전달하는 것까지 구현을 해보았다.
https://velog.io/@dhktjr0204/Spring-%EC%82%AC%EC%A7%84-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-1
요청받은 데이터을 이제 서버에서 처리를 해주는 것을 구현할 것이다.
@PutMapping("/edit/{id}")
public ResponseEntity<?> edit(@PathVariable Long id, BoardUpdateRequestDTO boardUpdateRequestDTO,
@RequestPart(value = "images", required = false) List<MultipartFile> images) {
Board board = boardService.updateBoard(id, boardUpdateRequestDTO, boardUpdateRequestDTO.getImageUrls(), images);
return ResponseEntity.ok("/board/" + id);
}
이 코드가 사진들을 처리할 Controller이다.
images라는 이름으로 파일 데이터들을 받고있고 boardUpdateRequestDTO의 imageUrls의 필드로 기존 이미지 사진을 받고있다.
위에 controller에서는 boardService.updateBoard라고 되어있지만 저 로직에서는 태그수정 및 게시글 수정 로직도 포함되어있으므로 사진 수정하는 로직만 살펴보겠다.
@Transactional
@Override
public void updateFileList(Board board, List<String> originalFiles, List<MultipartFile> newFiles) {
List<Image> images = imageRepository.findAllByBoard_IdOrderByOrder(board.getId())
.orElseThrow(BoardNotFoundException::new);
//새로 전송된 사진들이 시작할 순서
int orderIndex = 0;
//만약 기존 이미지가 모두 지워졌다면 DB에 저장된 이미지들 모두 삭제
if (originalFiles == null) {
for (Image image : images) {
imageRepository.delete(image);
deleteS3(image.getName());
}
} else {
// 이미 저장된 사진들의 순서를 바꿔준다.
orderIndex = originalFiles.size();
for (Image image : images) {
int index = originalFiles.indexOf(image.getName());
//만약 originalFiles에 없으면 사용자가 삭제한 사진이기 때문에 삭제
if (index == -1) {
imageRepository.delete(image);
deleteS3(image.getName());
} else {
//사진이 포함되어있다면 순서 업데이트
image.update(index + 1);
}
}
}
//새로운 파일 s3에 저장
if (newFiles != null) {
for (int i = 0; i < newFiles.size(); i++) {
String fileName = saveS3(newFiles.get(i));
saveImageInDB(board, fileName, orderIndex + i + 1);
}
}
}
엄청.. 길다... 하나씩 살펴보겠다.
List<Image> images = imageRepository.findAllByBoard_IdOrderByOrder(board.getId())
.orElseThrow(BoardNotFoundException::new);
기존 게시글에 저장되어있던 사진들을 가져온다.
if (originalFiles == null) {
for (Image image : images) {
imageRepository.delete(image);
deleteS3(image.getName());
}
}
만약 전달받은 기존 파일이 없다 -> 사용자가 게시글에 포함되어있던 사진들을 모두 삭제한 것이다.
따라서 데이터베이스에 있던 기존 파일들을 삭제해준다. 또한, s3에 있던 사진들도 삭제한다.
else {
// 이미 저장된 사진들의 순서를 바꿔준다.
orderIndex = originalFiles.size();
for (Image image : images) {
int index = originalFiles.indexOf(image.getName());
//만약 originalFiles에 없으면 사용자가 삭제한 사진이기 때문에 삭제
if (index == -1) {
imageRepository.delete(image);
deleteS3(image.getName());
} else {
//사진이 포함되어있다면 순서 업데이트
image.update(index + 1);
}
}
}
- orderIndex = 사진의 순서를 결정하는 index이다. 앞서 내가 구현했던 로직은 이미 저장된 사진들이 새로 업로드된 사진들보다 먼저 올 수 밖에 없기 때문에, 기존 사진들의 size만큼 orderIndex를 설정해주었다.
- int index = originalFiles.indexOf(image.getName()) = 데이터베이스에 저장된 사진 이름들 중 전달 받지 않은 사진이 있는지 확인하는 변수이다. (기존 사진 중 삭제할 사진 찾기)
- if (index == -1) = 만약 index가 -1이라면 전달받지 못한 것이다. 즉, 사용자가 그 사진을 삭제한 것이다. 그렇기 때문에 데이터베이스 및 s3에서 삭제한다.
- 만약 사진이 포함되어있다면 순서를 업데이트해준다. 프론트에서 사진을 순서대로 보냈기 때문에 index대로 업데이트하면 됨
이번엔 새로운 사진 저장이다.
//새로운 파일 s3에 저장
if (newFiles != null) {
for (int i = 0; i < newFiles.size(); i++) {
String fileName = saveS3(newFiles.get(i));
saveImageInDB(board, fileName, orderIndex + i + 1);
}
}
- 만약 List<
MultipartFile>에 아무것도 전달된게 없다면 사용자가 새로운 사진을 업로드하지 않았다는 것이다. 그렇다면 업로드할 필요가 없으니 넘어간다.- if (newFiles != null) = 전달받은 파일이 있을 시에만 s3와 데이터베이스에 저장한다.
- saveImageInDB(board, fileName, orderIndex + i + 1) = orderIndex는 아까 기존 사진에서 지정한 index이다. 기존 사진들은 업로드된 사진보다 무조건 앞에 있기 때문에 기존 사진 갯수만큼 밀려난다.
이렇게 구현하니 정상적으로 잘 저장되고 순서도 제대로 나오게 되었음
