[게시글 수정에서 필요한 로직] 1. 게시글 수정 (이미 게시글 수정 구현 과정에서 구현되어있음) 2. 이전에 첨부되어있던 파일 삭제(할 수도 있고 안 할 수도 있다.) - 첨부파일이 존재한다면 옆에 파일 삭제 버튼도 같이 보여야 한다. - 파일 삭제 버튼을 누른다고 해서 바로 삭제되는 것은 아니다. - 파일 삭제 버튼을 누르면 파일 삭제 버튼이 삭제 취소 버튼으로 바뀐다. - 삭제 취소 버튼을 누르면 다시 파일 삭제 버튼으로 바뀐다. - 최종적으로 수정 완료 버튼을 눌렀을 때 파일 삭제 버튼이 눌린 파일만 완전히 삭제된다. 3.새롭게 첨부한 파일 등록(할 수도 있고 안 할 수도 있다.) (이미 첨부파일 업로드 구현 과정에서 구현되어있음)
[ 1. BoardController 수정 ]
/** 기존 게시글 수정 처리 */
@PutMapping("/board/{boardIdx}")
public String modifyBoard(@PathVariable("boardIdx") int boardIdx, BoardDto board) throws Exception{
boardService.modifyBoard(board);
return "redirect:/board/" + boardIdx;
}
/**
*수정 후 게시글 수정 처리
* files는 새롭게 첨부할 파일을 등록할 때 필요하다.
* 이미 첨부되었는 파일을 삭제할 때 필요한 데이터는 이미 board에 들어있음 (경로)
*/
@PutMapping("/board/{boardIdx}")
public String modifyBoard(@PathVariable("boardIdx") int boardIdx,
@ModelAttribute BoardDto board,
@RequestParam("files") List<MultipartFile> files) throws Exception{
boardService.modifyBoard(board, files);
return "redirect:/board/" + boardIdx;
}
[ 2. BoardService 수정 ]
/** 기존 게시글 수정 */
public void modifyBoard(BoardDto board) throws Exception{
boardMapper.modifyBoard(board);
}
/** 수정 후 게시글 수정 */
public void modifyBoard(BoardDto board, List<MultipartFile> files) throws Exception{
// 게시글 수정
boardMapper.modifyBoard(board);
// 새로운 첨부파일 등록
boardFileService.insertFile(board, files);
// 기존 첨부파일 삭제
boardFileService.deleteFile(board);
}
[ 3. BoardFileService 추가 ]
/** 첨부파일 삭제 */
public void deleteFile(BoardDto board)throws Exception{
List<BoardFileDto> fileList = board.getFileList();
// fileList가 null이거나 비어있을 경우 종료(이미 첨부되어 있던 파일 삭제를 안할 경우)
if(fileList == null || fileList.isEmpty()) {
return;
}
// 서버 컴퓨터에서 삭제
for(BoardFileDto oneFile : fileList) {
String path = oneFile.getStoredFilePath();
File file = new File(path);
if(!file.exists()) {
log.info("존재하지 않는 파일");
return;
}
if(file.delete()) {
log.info("삭제 성공",oneFile.getOriginalFileName());
}else {
log.info("삭제 실패",oneFile.getOriginalFileName());
}
}
// 첨부파일 번호 리스트로 넣어주기
List<Integer> idxs =new ArrayList<Integer>();
for(BoardFileDto oneFile : fileList) {
idxs.add(oneFile.getIdx());
}
// 데이터베이스에서 파일 정보 상태 삭제로 바꾸기
boardMapper.deleteFile(idxs);
}
[ 4. 쿼리 추가 ]
<update id="deleteFile" parameterType ="int">
/* 파일 삭제 상태로 변경 */
<![CDATA[
UPDATE
t_file
SET
deleted_yn = 'Y',
updator_id = 'admin',
updated_datetime = Now()
WHERE
idx IN (
]]>
<foreach collection="list" item="item" separator=",">
#{item}
</foreach>
)
</update>
[ 5. html 수정 ]
<form id="frm" method="post" th:action="'/board/'+ ${boardIdx}" enctype="multipart/form-data">
.. 테이블(formdata) ..
// 메서드 put으로 설정
<input type="hidden" id="method" name="_method" value="put"/>
// 파일삭제 버튼은 동적으로 생성되기 때문에 첨부파일 없을 경우 존재하지 않기 때문에
// 따로 div를 만들어서 이벤트 핸들러를 등록해줄 예정이다.
<div class="eventDiv">
<div class="file_list" th:if="${board.fileList != null and board.fileList.size() > 0}">
[ 첨부파일 ]
<div th:each="list, stat : ${board.fileList}" >
<span class="file_bg" th:href="@{/board/file(idx=${list.idx}, boardIdx=${list.boardIdx})}" th:text="|${list.originalFileName} (${list.fileSize} kb)|"></span>
/*
* 선택된 파일만 name을 동적으로 추가해서 컨트롤러로 값을 넘겨 줄 예정
* 컨트롤러에서는 BoardDto에서 board.setFileList(List<BoardFileDto>)를 통해서 매핑할 예정
* 즉, fileList의 name은 List 형태여야한다.
* 서버 컴퓨터에서 파일을 삭제할 때 필요한 경로와 데이터베이스에서 파일을 삭제할 때 필요한 pk만 받아온다.
*/
<input type="hidden" class="file_idx" th:value="${list.idx}">
<input type="hidden" class="file_path" th:value="${list.storedFilePath}">
<button type="button" class="deleteFileBtn btn">파일삭제</button>
</div>
</div>
</div>
<input type="file" id="files" name="files" multiple="multiple">
<input type="hidden" id="boardIdx" name="boardIdx" th:value="${board.boardIdx}">
<button type="button" id="modifyBtn" class="btn">수정완료</button>
</form>
[ 6. 자바스크립트 수정 ]
// 이전에 첨부되어있던 파일 삭제(할 수도 있고 안 할 수도 있다.)
const eventDiv = document.querySelector('.eventDiv');
eventDiv.addEventListener('click', e => {
const files = document.querySelector('#files');
const filesInfo = files.files;
console.log(filesInfo);
if(e.target.classList.contains('deleteFileBtn')){
const fileDiv = e.target.closest('div');
const fileSpan = fileDiv.querySelector('span');
fileSpan.className = 'file_delete_bg';
e.target.classList.toggle('deleteFileBtn');
e.target.classList.toggle('cancleFileBtn');
e.target.textContent = '삭제취소';
}else if(e.target.classList.contains('cancleFileBtn')){
const fileDiv = e.target.closest('div');
const fileSpan = fileDiv.querySelector('span');
fileSpan.className = 'file_bg';
e.target.classList.toggle('deleteFileBtn');
e.target.classList.toggle('cancleFileBtn');
e.target.textContent = '파일삭제';
}
});
수정할 때 이미 첨부되어있던 파일 삭제, 파일 새롭게 첨부 구현 끝
게시글 수정 화면이미 첨부되어있던 파일 삭제 선택
파일 새롭게 첨부수정 완료!
[ 게시글 삭제할 때 파일도 같이 삭제되게 하는 경우...] - 굳이 삭제할 파일을 선택하지 않고 전부 삭제하면 되기 때문에 boardDtail.html(게시글 상세 보기 화면에서) 을 아래와 같이 추가한다.
<div class="file_list" th:if="${board.fileList != null and board.fileList.size() > 0}">
[ 첨부파일 ]
// 게시글 수정에서는 input 태그의 name을 자바스크립트를 통해 동적으로 추가해줬다.
// 게시글 삭제에서는 모든 파일을 삭제할 것이기 때문에 굳이 선택해서 추가할 필요가 없다.
// th:block을 추가해서 a태그와 input태그를 반복하게 한다.
<th:block th:each="list, stat : ${board.fileList}">
<a th:href="@{/board/file(idx=${list.idx}, boardIdx=${list.boardIdx})}" th:text="|${list.originalFileName} (${list.fileSize} kb)|"></a>
<input type="hidden" class="file_idx" th:name="'fileList[' + ${stat.index} + '].idx'" th:value="${list.idx}">
<input type="hidden" class="file_path" th:name="'fileList[' + ${stat.index} + '].storedFilePath'" th:value="${list.storedFilePath}">
</th:block>
</div>
- BoardController
/** 기존 게시글 삭제 처리 */
@DeleteMapping("/board/{boardIdx}")
public String deleteBoard(@PathVariable("boardIdx") int boardIdx) throws Exception{
boardService.deleteBoard(boardIdx);
return "redirect:/board";
}
// 수정 후 게시글 삭제 처리
@DeleteMapping("/board/{boardIdx}")
public String deleteBoard(@ModelAttribute BoardDto board) throws Exception{
boardService.deleteBoard(board);
return "redirect:/board";
}
- BoardService
/** 기존 게시글 삭제 */
public void deleteBoard(int boardIdx) throws Exception{
boardMapper.deleteBoard(boardIdx);
}
/** 수정 후 게시글 삭제 */
public void deleteBoard(BoardDto board) throws Exception{
// 게시글 삭제
int boardIdx = board.getBoardIdx();
boardMapper.deleteBoard(boardIdx);
// 첨부파일 삭제
boardFileService.deleteFile(board);
}