/save의 post요청을 처리하다가 오류가 생겼다. 처음에는 리다이렉션의 문법 오류인줄 알았는데 원인은 따로 있었다.
java.io.IOException: java.nio.file.NoSuchFileException: C:\springboot_img\1724750433697
오류는 위와 같은데 파일이 첨부되었을 때 번호를 부여하고 저장하는 코드가 실행되었다.
파일을 첨부하지 않았는데 파일이 첨부되었을 때의 로직이 실행된 것이다.
db를 확인해보니 파일을 첨부하지 않는 파일들도 file_attatched가 1로 저장되어 있었다.
dto를 출력해보니
boardDTO = BoardDTO(id=null, boardWriter=ㅎㅎ, boardPass=ㅎㅎ, boardTitle=ㅎㅎ, boardContents=ㅎㅎ, boardHits=0, boardCreatedTime=null, boardUpdatedTime=null, boardFile=[org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@49f581d0], originalFileName=null, storedFileName=null, fileAttached=0)
다음과 같이 나왔다.
검색해보니
1, StandardMultipartHttpServletRequest$StandardMultipartFile
MultipartFile 인터페이스의 구체적인 구현체이다.
2. @49f581d0
객체를 참조할 수 있는 해시코드.
문제가 생긴 코드는 다음과 같다.
처음에는 entity나 dto에 문제가 있는 줄 알고 강의도 다시 들어가며 삽질을 열심히 했는데 맨 처음 과정의 getBoardFile에 문제가 있었다.
public void save(BoardDTO boardDTO) throws IOException {
logger.info("boardDTO = " + boardDTO);
// 파일 첨부 여부에 따라 로직 분리
if (boardDTO.getBoardFile().isEmpty()) {
System.out.println("파일 첨부 없음");
// 1. 첨부 파일 없음.
BoardEntity boardEntity = BoardEntity.toSaveEntity(boardDTO); // dto->entity
boardRepository.save(boardEntity); // repository에 저장
} else {
System.out.println("파일 첨부 있음");
// 2. 첨부 파일 있음.
/*
1. DTO에 담긴 파일을 꺼냄
2. 파일의 이름 가져옴
3. 서버 저장용 이름을 만듦
// 내사진.jpg => 839798375892_내사진.jpg
4. 저장 경로 설정
5. 해당 경로에 파일 저장
6. board_table에 해당 데이터 save 처리
7. board_file_table에 해당 데이터 save 처리
*/
// 자식 데이터가 여러개 있을 수 있는 상황이라 부모데이터 먼저 나와야함.
BoardEntity boardEntity = BoardEntity.toSaveFileEntity(boardDTO); // dto -> entity. db에 저장하기 전이라 id값이 없다.
Long savedId = boardRepository.save(boardEntity).getId(); // 엔티티를 데이터베이스에 저장하고, 생성된 기본 키 값을 얻음
BoardEntity board = boardRepository.findById(savedId).get(); // 1에서 저장된 기본 키를 사용하여 엔티티를 다시 조회
for (MultipartFile boardFile: boardDTO.getBoardFile()) {
String originalFilename = boardFile.getOriginalFilename(); // 2.
String storedFileName = System.currentTimeMillis() + "_" + originalFilename; // 3.
String savePath = "C:/springboot_img/" + storedFileName; // 4. C:/springboot_img/9802398403948_내사진.jpg
// String savePath = "/Users/사용자이름/springboot_img/" + storedFileName; // C:/springboot_img/9802398403948_내사진.jpg
boardFile.transferTo(new File(savePath)); // 5.
BoardFileEntity boardFileEntity = BoardFileEntity.toBoardFileEntity(board, originalFilename, storedFileName);
boardFileRepository.save(boardFileEntity);
}
}
}
logger.info("boardDTO.getBoardFile().isEmpty() = " + boardDTO.getBoardFile().isEmpty());
boardDTO.getBoardFile().isEmpty()를 출력했더니 false가 나왔다. 파일을 실제로 첨부하지 않았어도 비어있지 않게 된 것이다.
디버깅을 통해 boardFile에 접근해 보았더니 리스트가 비어있지 않았다! filename이 비어있지만 이건 정확히는 boardFile.get(0)이 비어있는 것이다.
그런데 왜 boardfile이 비어있지 않게 된것일까?
확인해보니 save.html에서 전달받은 직후부터 boardFile리스트의 크기가 1이다.
그래서 PostMapping에서 boardFile의 첫번째 요소가 비어있으면 리스트를 초기화하는 코드를 넣었더니 정상적으로 작동했다.