spring 23강 게시판 만들기4( 게시물 수정, 파일 첨부, 첨부파일 삭제, 게시물 삭제)
BoardContoller
//첨부파일 목록을 리턴
@RequestMapping("getAttach/{bno}")
public List<String> getAttach(@PathVariable int bno)
@RequestMapping("delete.do")
public String delete(int bno)
//게시물 내용 수정
@RequestMapping("update.do")
public String update(BoardDTO dto)
@RequestMapping("list.do") //세부적인 url pattern
public ModelAndView list( ... )
@RequestMapping("view.do")
public ModelAndView view (int bno, HttpSession session)
@RequestMapping("write.do")
public String write()
// write.jsp에서 입력한 내용들이 BoardDTO에 저장됨
@RequestMapping("insert.do")
public String insert ( ... )
BoardService
public void deleteFile(String fullName);
public List<String> getAttach(int bno);
public void create(BoardDTO dto)
public BoardDTO read(int bno)
public void update(BoardDTO dto) // BoardDAO의 update와 updateAttach 호출
public void delete(int bno)
public List<BoardDTO> listAll(String search_option, String keyword,int start, int end)
public void increaseViewcnt(int bno, HttpSession session)
public int countArticle(String search_option, String keyword)
BoardDAO
public void deleteFile(String fullName); //첨부파일 삭제
public List<String> getAttach(int bno); //첨부파일 정보
public void addAttach(String fullName); //첨부파일 저장
public void updateAttach(String fullName, int bno);//첨부파일 수정
public void create(BoardDTO dto) //글쓰기
public void update(BoardDTO dto) ; //글수정 //board.update
public void delete(int bno) //글삭제
public List<BoardDTO> listAll(String search_option, String keyword,int start, int end) //목록
public void increateViewcnt(int bno)//조회수 증가 처리
public int countArticle(String search_option, String keyword) //조회수 증가 처리
public BoardDTO read(int bno) throws Exception;//레코드 조회
파일 첨부 ( 드래그 & 드롭 )
어떤 파일이 올라왔는지 목록으로 보여주기 위해 첨부파일 테이블(attach)을 작성
:파일 이름(uuid/PK), 게시물 번호 ( reference board(bno)), 업로드 날짜
>view.jsp에서 common.js include
:이미지 파일인지 아닌지 체크하는 함수/ 파일이름, 이미지소스, 링크, 파일이름 리턴하는 함수 (AjaxUpload에 메핑된 함수 호출)
>view.jsp에서 .fileDrop 에 대한 drop 이벤트 처리의 디폴트처리를 막는다. ( e.preventDefault() )
첨부파일 테이블 작성
게시판.sql
drop table attach cascade constraints;
create table attach(
fullName varchar2(150) not null, --첨부파일 이름
bno number not null, --게시물 번호
regdate date default sysdate, --업로드 날짜
primary key(fullName) --첨부파일 이름에 uuid 사용, PK
);
--bno 컬럼에 foreign key 설정
alter table attach add constraint fk_board_attach
foreign key(bno) references board(bno);
-- board테이블의 bno를 참조하여 제약 설정
--board 테이블의 bno 컬럼을 위한 시퀀스 생성
drop sequence seq_board;
create sequence seq_board
start with 1
increment by 1;
common.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /*views/include/js/common.js*/ /*이미지 파일인지 확인 /정규표현식/ */ function checkImageType(fileName){ var pattern=/jpg|gif|png|jpeg/; return fileName.match(pattern); } function getFileInfo(fullName){ var fileName, imgsrc, getLink, fileLink; if(checkImageType(fullName)){ //이미지 파일인 경우 //(#{path}자바 파일 아니고 자바스크립트 파일이기때문에 EL문 못쓴다.) //AjaxUploadContoller에서 맵핑된 부분 imgsrc="/spring02/upload/displayFile?fileName=" +fullName; //파일의 확장자와 이름 구분 fileLink=fullName.substr(14); //14 인덱스~끝 var front=fullName.substr(0,12); //0~11 var end=fullName.substr(14); //썸네일이미지는 's_'가 들어가도록 설정했기때문에 // 12, 13번 인덱스를 뺀 이름을 저장해준다. getLink="/spring02/upload/displayFile?fileName=" +front+end; }else{ //이미지가 아닌 경우 fileLink=fullName.substr(12); getLink="/spring02/upload/displayFile?fileName=" +fullName; } // uuid_filename fileName=fileLink.substr(fileLink.indexOf("_")+1); return {fileName: fileName, imgsrc: imgsrc, getLink: getLink, fullName:fullName }; } |
이미지 타입 체크, 파일 정보 리턴하는 함수를 가진 js파일 작성
view.jsp에 common.js 등록
1 2 3 4 5 6 7 8 9 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <%@ include file="../include/header.jsp" %> <script src="${path}/include/js/common.js"></script> |
view.jsp 첨부파일 부분
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | $(".fileDrop").on("dragenter dragover",function(e){ //기본 효과 막음 e.preventDefault(); }); $(".fileDrop").on("drop",function(e){ e.preventDefault(); //첫번째 첨부파일 var files=e.originalEvent.dataTransfer.files; var file=files[0]; //폼 데이터에 첨부파일 추가 var formData=new FormData(); formData.append("file",file); $.ajax({ url: "${path}/upload/uploadAjax", data: formData, dataType: "text", processData: false, contentType: false, type: "post", success: function(data){ //console.log(data); //data : 업로드한 파일 정보와 Http 상태 코드 var fileInfo=getFileInfo(data); //console.log(fileInfo); var html="<a href='"+fileInfo.getLink+"'>"+ fileInfo.fileName+"</a><br>"; html += "<input type='hidden' class='file' value='" +fileInfo.fullName+"'>"; $("#uploadedList").append(html); } }); }); |
dataTransfer는 드래그앤드롭시 드래그된 데이터를 보관하는데에 사용되는 개체
( 드래그된 파일 중 첫번째 파일만 폼데이터에 append시키는데 왜???<<< )
첨부파일 이름 정보를 포함한 input type='hidden' 태그를 uploadedLsit에 추가
AjaxUploadController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | //uploadAjax에서 받은 데이터를 post방식으로 명시하여 실행 // 업로드한 파일은 MultipartFile 변수에 저장됨 @ResponseBody // json 형식으로 리턴 @RequestMapping(value = "/upload/uploadAjax", method = RequestMethod.POST, produces = "text/plain;charset=utf-8") public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception { // 업로드한 파일 정보와 Http 상태 코드를 함께 리턴 return new ResponseEntity<String>( UploadFileUtils.uploadFile(uploadPath, file.getOriginalFilename(), file.getBytes()), HttpStatus.OK); } |
위 리턴되는 ResponseEntity 객체가 success : function( data ) data(메시지와 상태코드)로 넘어옴
게시물 수정
view.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //수정 버튼 $("#btnUpdate").click(function(){ //첨부파일 이름들을 폼에 추가 var str=""; $("#uploadedList .file").each(function(i){ str+= "<input type='hidden' name='files["+i+"]' value='" +$(this).val()+"'>"; }); //첨부파일 이름들을 폼에 추가해서 BoardController의 update.do로 보낸다. //update.do로 가서 dto의 files(String[]타입)에 쌓인다. $("#form1").append(str); document.form1.action="${path}/board/update.do"; document.form1.submit(); }); |
id가 uploadedList이고 class가 file인 태그들(드래그앤드롭시 uploadedList에 append시킨 태그)
각각 처리 ( $( this ).val( )는 현재태그의 값)
처리한 데이터를 form1에 추가하여 BoardController의 update.do로 보낸다.
1 2 3 4 5 6 7 8 9 10 11 12 | //게시물 내용 수정 @RequestMapping("update.do") public String update(BoardDTO dto) throws Exception { System.out.println("dto:"+dto); if(dto != null) { boardService.update(dto); //레코드 수정 } // 수정 완료 후 목록으로 이동 //return "redirect:/board/list.do"; // 상세 화면으로 되돌아감 return "redirect:/board/view.do?bno="+dto.getBno(); } |
BoardServiceImpl의 update메서드에 @Transactional 이 붙어야한다.
레코드 추가는 성공했는데 파일 첨부에 실패한다면 rollback 시켜야하기때문
BoardServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 | @Transactional //트랜잭션 처리 method @Override public void update(BoardDTO dto) throws Exception { boardDao.update(dto); //board 테이블 수정 //attach 테이블 수정 String[] files=dto.getFiles(); if(files==null) return; for(String name : files) { System.out.println("첨부파일 이름:"+name); boardDao.updateAttach(name, dto.getBno()); } } |
1 2 3 4 5 | //레코드 수정 @Override public void update(BoardDTO dto) throws Exception { sqlSession.update("board.update", dto); } |
1 2 3 4 5 6 7 8 9 10 11 | //첨부파일 정보 수정 @Override public void updateAttach(String fullName, int bno) { Map<String,Object> map=new HashMap<>(); map.put("fullName", fullName); //첨부파일 이름 map.put("bno", bno); //게시물 번호 sqlSession.insert("board.updateAttach", map); } |
1 2 3 4 5 6 | <!-- 게시물 내용 수정 --> <update id="update"> update board set title=#{title}, content=#{content} where bno=#{bno} </update> | cs |
1 2 3 4 5 | <!-- 새로운 첨부파일 추가 --> <insert id="updateAttach"> insert into attach (fullName, bno) values ( #{fullName}, #{bno} ) </insert> |
'Spring > study' 카테고리의 다른 글
spring 25강 Spring Boot와 Oracle 연동, Thymeleaf Template 적용 (1) | 2019.07.10 |
---|---|
spring 24강 도로명 주소(daum api) (0) | 2019.07.08 |
@RequestBody 어노테이션과 @ReponseBody 어노테이션의 사용 (0) | 2019.07.05 |
spring 22강 게시판 만들기3( 상세 화면, 댓글 쓰기/댓글 목록/댓글 갯수) (0) | 2019.07.04 |
selectOne / selectList 쓰임 차이 (0) | 2019.07.04 |