JSP/JSP 예제

[jsp] 파일입출력 (board 게시물에 추가)

congs 2023. 5. 31. 12:19

1. MVNrepository 에서 추가 필요 파일 다운로드 (jar파일)

  • commons-fileiplode-1.4
  • commons-io-2.11.0
  • thumbnailator-0.4.17

파일입출력.zip
0.44MB

 

- 지금까지 다운받은 항목 -

라이브러리.zip
6.89MB

 


다운받았으면 lip파일에 넣어주기

 


 

2. webapp 폴더에 _fileuplode폴더 생성

:  _는 제일 상단에 위치하게 하기위해서 설정 (이름 오타안나게 주의!)

 


3. commons 패키지를 이용하여 파일 업로드할 예정!

  • thumbnail기능 : 큰 사진들을 빠르게 업로드할 수 있도록 (속도를 높이기 위해) 작게 줄여서 가져오는 기능
  • ppt파일 확인 - 30페이지부터

서블릿정리.pptx
1.16MB
이렇게 작게 나오도록 만드는게 썸네일 기능! (원래는 큰 사진)

 


 

 == 파일 업로드 처리 순서 ==

1. 폼 데이터가 multipart/form-data 형식으로 전송되었는지 확인 합니다.
                        = 그래야 parameter로 가져오기가 가능
2. 업로드된 파일과 폼 데이터를 담는 DiskFileUpload객체를 생성합니다.
                       = 이미지파일+여러 정보가 담길 객체 생성
3. DiskFileUpload 객체에서 아이템들을 추출합니다.
                       = 아이템 : 이미지파일, 정보 등
4. 추출된 아이템을 하나씩 꺼내서 폼데이터인지 파일인지 분석하여 각각 처리를 작성합니다.
                       = 데이터들은 DB에/ 이미지는 따로 저장 + DB에 이미지의 주소(경로)를 저장!

 


 

== register.jsp ==

 

4. board폴더의 register.jsp에 ( enctype / imageFile받는 input  ) 추가

-  폼 데이터를 multipart/form-data 형식으로 전송  = 그래야 parameter로 가져오기가 가능

- 추가부분

<form action="/brd/insert" method="post" enctype="multipart/form-data">
imageFile : <input type="file" id="file" name="image_file" 
					accept="image/png, image/jpg, image/jpeg, image/bmp, image/gif"> <br><br>

- 최종

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Board Register Page</title>
</head>
<body>
	<h1>register page</h1>
	
	<form action="/brd/insert" method="post" enctype="multipart/form-data">
		title : <input type="text" name="title"> <br>
		writer : <input type="text" name="writer" value="${ses.id }" readonly="readonly"> <br>
		content : <textarea rows="3" cols="30" name="content"></textarea> <br>
		imageFile : <input type="file" id="file" name="image_file" 
				accept="image/png, image/jpg, image/jpeg, image/bmp, image/gif"> <br>
				<!-- accept = placeholder처럼 사용하는거라 선택! -->
		<button type="submit">등록</button>
	</form>
</body>
</html>

 


 

5. board table에 파일경로가 들어갈 칼럼 추가

          + resources폴더 schema.sql에 칼럼추가부분 저장

alter table board add image_file varchar(100); // text도 가능

// text로 변경 시
alter table board modify image_file text;


 


 

== boardVO ==

 

6. boardVO 멤버변수에 image_file 추가

멤버변수
전체 출력
getter,setter / toString

package domain;

public class BoardVO {

	/* create table board(
		bno int not null auto_increment,
		title varchar(100) not null,
		writer varchar(100) not null,
		content text,
		reg_date datetime default now(),
		primary key(bno));
	 * 
	 * */
	
	
	private int bno;
	private String title;
	private String writer;
	private String content;
	private String reg_date;
	private int count;
	private String image_file;
	
	public BoardVO() {}

	//register(title, writer, content)
	public BoardVO(String title, String writer, String content) {
		this.title = title;
		this.writer = writer;
		this.content = content;
	}

	
	//list(bno, title, writer, reg_date, count)
	public BoardVO(int bno, String title, String writer, String reg_date, int count) {
		this.bno = bno;
		this.title = title;
		this.writer = writer;
		this.reg_date = reg_date;
		this.count = count;
	}

	//datail(전체)
	public BoardVO(int bno, String title, String writer, String content, 
			String reg_date, int count, String image_file) {
		this.bno = bno;
		this.title = title;
		this.writer = writer;
		this.content = content;
		this.reg_date = reg_date;
		this.count = count;
		this.image_file = image_file;
	} 



	//update(bno, title, content)
	public BoardVO(int bno, String title, String content) {
		this.bno = bno;
		this.title = title;
		this.content = content;
	}
	
	
	//getter,setter
	public int getBno() {
		return bno;
	}

	public void setBno(int bno) {
		this.bno = bno;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getWriter() {
		return writer;
	}

	public void setWriter(String writer) {
		this.writer = writer;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getReg_date() {
		return reg_date;
	}

	public void setReg_date(String reg_date) {
		this.reg_date = reg_date;
	}
	

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}
	
	
	

	public String getImage_file() {
		return image_file;
	}

	public void setImage_file(String image_file) {
		this.image_file = image_file;
	}

	@Override
	public String toString() {
		return "BoardVO [bno=" + bno + ", title=" + title + ", writer=" + writer + ", content=" + content
				+ ", reg_date=" + reg_date + ", count=" + count + ", image_file=" + image_file + "]";
	}

	

	
	
	 
}

 

 


 

== BoardController ==

 

7.  boardController 에 추가 + case "insert" 변경

 

- 상단 멤버변수에 추가 -

//파일 경로를 저장할 변수
	private String savePath;
	private final String UTF8 = "UTF-8"; //인코딩 설정시

- case "insert" 변경 -

case "insert":
			try {
				
				//파일을 업로드할 물리적인 경로를 설정
				savePath = getServletContext().getRealPath("/_fileUpload");
				log.info(">>>파일 저장 경로: " + savePath);
				//실제경로를 가져와! "webapp안의_fileUplode"
				
				File fileDir = new File(savePath); //File은 java.io에서 import
				//파일의 저장위치를 담고 있는 객체생성
				
				DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(); 
				//아이템을 담는,,?
				fileItemFactory.setRepository(fileDir);
				//파일의 저장위치를 담고 있는 객체를 저장하기
				fileItemFactory.setSizeThreshold(2*1024*1024);
				//파일 저장을 위한 임시 메모리의 용량을 설정하기 : byte단위 => 2MB = 2*1024*1024
				
				BoardVO bvo = new BoardVO();
				
				ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
				//multipart/form-data형식으로 넘어온 request객체를 다루기 쉽게 변환해주는 역할
				
				List<FileItem> itemList = fileUpload.parseRequest(request);
				//request객체를 FileItem의 리스트로 담아
				for(FileItem item : itemList) {
					//title = __, writer=__..이런식으로 key=velue 형태롤 들어가 있음
					switch(item.getFieldName()) { //key값을 가져오는 역할
					case "title":
						bvo.setTitle(item.getString(UTF8)); 
						//가져올때는 인코딩 형식을 담아서 변환해 가져와야 안깨짐!
						//UTF8( 위에 "UTF-8"을 저장해놓은 변수) 또는 "UTF-8"로 작성가능 
						break;
					case "writer": 
						bvo.setWriter(item.getString(UTF8));
						break;
					case "content":
						bvo.setContent(item.getString(UTF8));
						break;
					case "image_file":
						//먼저 이미지가 있는지 없는지부터 체크 
						if(item.getSize() > 0) { //데이터의 크기로 유무확인 (size) //이미지 파일이 있는 경우
							String fileName = item.getName().substring(item.getName().lastIndexOf("/")+1);
							log.info(">>>fileName 시간넣기 전 : " + fileName); //cat.jpg
							//.getName() : 경로를 포함한 파일의 이름 (___.___/cat.jpg) -> 마지막 cat.jpg만 가져오기
							
							fileName = System.currentTimeMillis()+"_"+fileName; 
							log.info(">>>fileName 시간넣은 후 : " + fileName);
							//파일 이름 앞에 _저장시간넣어주기
							
							File uploadFilePath = new File(fileDir+File.separator+fileName);
							log.info(">>>실제 업로드하는 파일의 경로: "+ uploadFilePath);
							
							try {
								item.write(uploadFilePath); //자바객체를 디스크에 저장
								bvo.setImage_file(fileName);
								
								//썸네일 작업 : 리스트페이지에서 트래픽 과다사용을 막기위해
								Thumbnails.of(uploadFilePath).size(75, 75)
								.toFile(new File(fileDir+File.separator+"th_"+fileName));
								
							} catch (Exception e) {
								log.info("파일 저장 오류 발생! file writer on disk fail");
								e.printStackTrace();
							}							
						}
						break;
					}
				}		
				isOk = bsv.insert(bvo);
				log.info(">>> insert " + (isOk > 0 ? "성공" : "실패"));
				
			} catch (Exception e) {
				log.info("controller오류");
				e.printStackTrace();
			}
			destPage = "page"; 
			break;

- 변경된 boardController 전체부분 - 

package controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import domain.BoardVO;
import domain.PagingVO;
import handle.PagingHandler;
import net.coobird.thumbnailator.Thumbnails;
import service.BoardService;
import service.BoardServiceImpl;


@WebServlet("/brd/*")
public class BoradController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static final Logger log = LoggerFactory.getLogger(BoradController.class);
	private RequestDispatcher rdp; //목적지주소로 원하는값들 이동
	private String destPage; //목적지 주소를 저장해주는 변수
	private int isOk; //DB의 insert, update, delete의 결과를 받는 변수
	private BoardService bsv; //인터페이스 생성
	//파일 경로를 저장할 변수
	private String savePath;
	private final String UTF8 = "UTF-8"; //인코딩 설정시
	
	

    public BoradController() {
    	bsv = new BoardServiceImpl(); //인터페이스의 구현체 생성(class)
    	
    }


	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setCharacterEncoding("utf-8"); 
		response.setContentType("text/html; charset=utf-8"); //html형태로 가져와서 뿌려라!
		
		String uri = request.getRequestURI(); //전체 요청경로
		log.info(">>uri: " +uri);
		String path = uri.substring(uri.lastIndexOf("/")+1);
		log.info(">>path: " +path);
		
		switch(path) {
		case "register":
			destPage = "/board/register.jsp";
			break;
		
		case "insert":
			try {
				
				//파일을 업로드할 물리적인 경로를 설정
				savePath = getServletContext().getRealPath("/_fileUpload");
				log.info(">>>파일 저장 경로: " + savePath);
				//실제경로를 가져와! "webapp안의_fileUplode"
				
				File fileDir = new File(savePath); //File은 java.io에서 import
				//파일의 저장위치를 담고 있는 객체생성
				
				DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(); 
				//아이템을 담는,,?
				fileItemFactory.setRepository(fileDir);
				//파일의 저장위치를 담고 있는 객체를 저장하기
				fileItemFactory.setSizeThreshold(2*1024*1024);
				//파일 저장을 위한 임시 메모리의 용량을 설정하기 : byte단위 => 2MB = 2*1024*1024
				
				BoardVO bvo = new BoardVO();
				
				ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
				//multipart/form-data형식으로 넘어온 request객체를 다루기 쉽게 변환해주는 역할
				
				List<FileItem> itemList = fileUpload.parseRequest(request);
				//request객체를 FileItem의 리스트로 담아
				for(FileItem item : itemList) {
					//title = __, writer=__..이런식으로 key=velue 형태롤 들어가 있음
					switch(item.getFieldName()) { //key값을 가져오는 역할
					case "title":
						bvo.setTitle(item.getString(UTF8)); 
						//가져올때는 인코딩 형식을 담아서 변환해 가져와야 안깨짐!
						//UTF8( 위에 "UTF-8"을 저장해놓은 변수) 또는 "UTF-8"로 작성가능 
						break;
					case "writer": 
						bvo.setWriter(item.getString(UTF8));
						break;
					case "content":
						bvo.setContent(item.getString(UTF8));
						break;
					case "image_file":
						//먼저 이미지가 있는지 없는지부터 체크 
						if(item.getSize() > 0) { //데이터의 크기로 유무확인 (size) //이미지 파일이 있는 경우
							String fileName = item.getName().substring(item.getName().lastIndexOf("/")+1);
							log.info(">>>fileName 시간넣기 전 : " + fileName); //cat.jpg
							//.getName() : 경로를 포함한 파일의 이름 (___.___/cat.jpg) -> 마지막 cat.jpg만 가져오기
							
							fileName = System.currentTimeMillis()+"_"+fileName; 
							log.info(">>>fileName 시간넣은 후 : " + fileName);
							//파일 이름 앞에 _저장시간넣어주기
							
							File uploadFilePath = new File(fileDir+File.separator+fileName);
							log.info(">>>실제 업로드하는 파일의 경로: "+ uploadFilePath);
							
							try {
								item.write(uploadFilePath); //자바객체를 디스크에 저장
								bvo.setImage_file(fileName);
								
								//썸네일 작업 : 리스트페이지에서 트래픽 과다사용을 막기위해
								Thumbnails.of(uploadFilePath).size(75, 75)
								.toFile(new File(fileDir+File.separator+"th_"+fileName));
								
							} catch (Exception e) {
								log.info("파일 저장 오류 발생! file writer on disk fail");
								e.printStackTrace();
							}							
						}
						break;
					}
				}		
				isOk = bsv.insert(bvo);
				log.info(">>> insert " + (isOk > 0 ? "성공" : "실패"));
				
			} catch (Exception e) {
				log.info("controller오류");
				e.printStackTrace();
			}
			destPage = "page"; 
			break;
			
			
//			try {
//				String title = request.getParameter("title");
//				String writer = request.getParameter("writer");
//				String content = request.getParameter("content");
//				
//				BoardVO bvo = new BoardVO(title, writer, content);
//				
//				isOk = bsv.insert(bvo);
//				log.info(">>> insert " + (isOk > 0 ? "성공" : "실패"));
//				
//				
//			} catch (Exception e) {
//				log.info("controller오류");
//				e.printStackTrace();
//			}
//			destPage = "/"; 
//			break;
			
		
		case "list":
			try {
				List<BoardVO> list = new ArrayList<>();
				list = bsv.list();
				request.setAttribute("list", list);
				log.info(">>> list출력");
				
			} catch (Exception e) {
				log.info("controller오류");
				e.printStackTrace();
			}
			
			destPage = "page";
			break;
		
		case "page":
			try {
				int pageNo = 1;
				int qty = 10;
				
				//검색
				String type ="";
				String keyword="";
				
				if(request.getParameter("type") != null) {
					type = request.getParameter("type");
					keyword = request.getParameter("keyword");
					log.info(">>> type : " + type + "/  >>> ketword: " + keyword);
					
				}
				
				
				if(request.getParameter("pageNo") != null) {
					pageNo = Integer.parseInt(request.getParameter("pageNo")); 
					qty = Integer.parseInt(request.getParameter("qty")); 
				}
				PagingVO pgvo = new PagingVO(pageNo, qty);
				
				pgvo.setType(type);
				pgvo.setKeyword(keyword);
				log.info(">>> pgvo set설정확인: "+pgvo.toString());
				
				//전체 페이지의 개수
				int totCount = bsv.getTotal(pgvo);
				log.info("전체페이지의 수: "+totCount);
				
				//limit을 이용해 맞는 select List호출!
				//startPage, qty
				List<BoardVO> list = bsv.getPageList(pgvo);
				log.info(">>> list.size: "+ list.size());
				
				PagingHandler ph = new PagingHandler(pgvo, totCount);
				request.setAttribute("pgh", ph);
				request.setAttribute("list", list);
				log.info("pageList 성공");
				
				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			destPage = "/board/list.jsp";
			break; 
		

			
		case "detail":
			try {
				int bno = Integer.parseInt(request.getParameter("bno"));
				BoardVO bvo = new BoardVO();
				request.setAttribute("bvo", bsv.detail(bno));
				
				log.info(">>> 게시판 상세가져오기 성공");
			
			} catch (Exception e) {
				log.info("controller오류");
				e.printStackTrace();
			}
			
			destPage = "/board/detail.jsp";
			break;
		
		case "modify":
			try {
				int bno = Integer.parseInt(request.getParameter("bno"));
				BoardVO bvo = new BoardVO();
				request.setAttribute("bvo", bsv.modify(bno));
				
				log.info(">>> 게시판 수정에 가져오기 성공");
			
			} catch (Exception e) {
				log.info("controller오류");
				e.printStackTrace();
			}
			
			destPage = "/board/modify.jsp";
			break;
			
		case "edit":
			try {
				int bno = Integer.parseInt(request.getParameter("bno"));
				String title = request.getParameter("title");
				String content = request.getParameter("content");
				log.info(title);
				
				BoardVO bvo = new BoardVO(bno, title, content);
						
				isOk = bsv.edit(bvo);
				log.info(">>> edit " + (isOk > 0 ? "성공" : "실패"));
				
			} catch (Exception e) {
				log.info("controller오류");
				e.printStackTrace();
			}
			
			destPage="/brd/page";
			break;
			
		case "remove":
			int bno = Integer.parseInt(request.getParameter("bno"));
			
			isOk = bsv.remove(bno);
			log.info(">>> remove " + (isOk > 0 ? "성공" : "실패"));
			
			destPage="/brd/page";
			break;
		}
		
		rdp = request.getRequestDispatcher(destPage);
		rdp.forward(request, response);
		
	}


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		service(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		service(request, response);
	}

}

 

== boardMapper ==

 

8. 연결되어있는 boardMapper의 insert구문에 image_file 추가

<insert id="reg" parameterType="bvo"> <!-- mvo = domain.mvo / mvo = mvo객체가 들어올꺼야! -->
  		insert into board(title, writer, content, image_file) 
  		values(#{title}, #{writer}, #{content}, #{image_file})
</insert>

 

- 여기까지 하면 나오는 출력화면 -

 

입력하면
생성되고
들어가면 이미지는 아직 안뜸!


...
DB에 추가 된것을 확인가능 (이미지는 주소가)


콘솔창에 뜬 주소로 들어가면!


사진이 저장되어있는것을 확인!

 



 

9. list에 이미지가 작게(썸네일) 출력되도록 만들기

 

- 썸네일을 넣을 위치 -

빨강 네모에 넣고 싶어!

 

- borad의 list.jsp에 추가 -

<tbody>
			<c:forEach items="${list }" var="list">
			<tr>
				<td>${list.bno }</td>
						
				<td>
					<c:if test="${list.image_file ne null && list.image_file ne ''}">
						<img alt="사진안떠욥" src="/_fileUpload/th_${list.image_file}">
					</c:if>
					<a href="detail?bno=${list.bno}">${list.title }</a>
				</td>
				<td>${list.writer }</td>
				<td>${list.reg_date }</td>
				<td>${list.count }</td>
			</tr>
			</c:forEach>
</tbody>

 

- boradMapper에 image_file추가 -

<select id="selectList" parameterType="pgvo" resultType="bvo">
  		select * from (
  			select bno from board where bno>0
  			<include refid="search"></include>
  			order by bno desc
  			limit #{pageStart}, #{qty}
  		) a left join board b
  		on a.bno = b.bno
</select>

//--------------------------------------------------------------------------

<select id="selectList" parameterType="pgvo" resultType="bvo">
  		select a.bno, title, writer, reg_date, count, image_file from (
  			select bno from board where bno>0
  			<include refid="search"></include>
  			order by bno desc
  			limit #{pageStart}, #{qty}
  		) a left join board b
  		on a.bno = b.bno
</select>

 


 

 

== 최종 출력화면 ==

 


 

 



 

== 이미지파일 상세페이지에 뜨도록 설정 ==

 

 

1. detail상세 페이지에 그림파일 원본 출력하기

<tr>
	<th>첨부파일</th>
	<td>
		<c:if test="${bvo.image_file ne null && bvo.image_file ne ''}">
			<img alt="사진안떠욥" src="/_fileUpload/${bvo.image_file}">
		</c:if>
	</td>
</tr>

 

 


 

== 이미지파일 수정하기 ==

 

1. board폴더의 modify 수정페이지에 파일수정 추가

- 추가부분

<form action="/brd/modify" method="post" enctype="multipart/form-data">
<tr>
		<th>첨부파일</th>
		<td>
			<img alt="이미지 없송" src="/_fileUpload/th_${bvo.image_file}">
			<input type="hidden" name="image_file" value="${bvo.image_file}">
			<input type="file" name="new_file"> 
		</td>
</tr>

- 최종

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>modify 게시판 수정</title>
</head>
<body>
	<h3>modify 게시판 수정 페이지</h3>
	<form action="/brd/edit" method="post" enctype="multipart/form-data">
		<table class="table table-hover">
			<tr>
				<th>번호</th>
				<td><input type="text" name="bno" value="${bvo.bno }" readonly="readonly"></td>
			</tr>
			<tr>
				<th>제목</th>
				<td><input type="text" name="title" value="${bvo.title }"></td>
			</tr>
			<tr>
				<th>사용자</th>
				<td><input type="text" name="writer" value="${bvo.writer }" readonly="readonly"></td>
			</tr>
			<tr>
				<th>내용</th>
				<td><textarea name="content">${bvo.content }</textarea></td>
			</tr>
			<tr>
				<th>작성일자</th>
				<td><input type="text" name="reg_date" value="${bvo.reg_date }" readonly="readonly"></td>
			</tr>
			<tr>
				<th>첨부파일</th>
				<td>
					<img alt="이미지 없슈" src="/_fileUpload/th_${bvo.image_file}"> <!-- 기존 이미지 -->
					<input type="hidden" name="image_file" value="${bvo.image_file}"><!-- 기존이미지 주소 -->
					<input type="file" name="new_file"> <!-- 새 이미지 -->
				</td>
			</tr>
		</table>	
		<button type="submit" onclick="handClick()">수정</button>
	</form>
	
	<script type="text/javascript"> //js를 사용하겠습니다
		function handClick() {
			alert("수정하였습니다.");
		}
	</script>
		

</body>
</html>

설정하면 보이는 썸네일 그림

 

 

2. boardController에 case "edit" 새로 작성

 

case "edit":
			
	try {
		savePath = getServletContext().getRealPath("/_fileUpload");
		File fileDir = new File(savePath);
        
		DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
		fileItemFactory.setRepository(fileDir);
		fileItemFactory.setSizeThreshold(2*1024*1024);
				
		BoardVO	 bvo = new BoardVO();
		ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory);
		log.info(">>>update 준비");
				
		List<FileItem> itemList = fileUpload.parseRequest(request);
				
		String old_file = null;
        for(FileItem item : itemList) {
		switch(item.getFieldName()) {
        case "bno":
				bvo.setBno(Integer.parseInt( item.getString(UTF8))); 		
                break;
		case "title":
				bvo.setTitle(item.getString(UTF8)); 
				break;
		case "content":
				bvo.setContent(item.getString(UTF8));
				break;
		case "image_file":
				//기존 파일의 이름을 가져와서 담기
				old_file = item.getString(UTF8);
				break;
			case "new_file":
				if(item.getSize() > 0) {
					//수정할 이미지 파일(등록할)이 있는 경우 
					
					if(old_file != null) {
						//old_file이 있는 경우
						//파일핸들러를 호출해서 기존 파일을 삭제
						FileHandler fileHandler = new FileHandler();
						isOk = fileHandler.deleteFile(old_file, savePath);	
					}
					//이름 설정
					String fileName = item.getName().substring(
					item.getName().lastIndexOf("/")+1);//이름
					//lastIndexOf(File.separatoe)+1도 동일
					log.info(">>>new_fileName : "+ fileName);
							
					//실제저장이름
					fileName = System.currentTimeMillis()+"_"+fileName;
					File uploadFilePath = new File(fileDir + File.separator + fileName);
					
					try {
						item.write(uploadFilePath);
						bvo.setImage_file(fileName);
						log.info(">>> bvo.image_file : " + bvo.getImage_file());
						
						//썸네일 작업
						Thumbnails.of(uploadFilePath).size(75, 75)
						.toFile(new File(fileDir+File.separator+"th_"+fileName));
								
					} catch (Exception e) {
						log.info(">>> file update on disk fall");
						e.printStackTrace();
					}
						
				}else {//새로운파일을 넣지 않은 경우
					bvo.setImage_file(old_file);
					//기존의 파일을 다시 bvo객체에 저장하기
				}
			break;
			}
			
		}				
		isOk = bsv.edit(bvo);
		log.info(">>> edit " + (isOk > 0 ? "성공" : "실패"));
		
	} catch (Exception e) {
		log.info("controller오류");
		e.printStackTrace();
	}
	destPage="/brd/page";
	break;

 

3. boardMapper의 update문 추가하면 끝!

<update id="update" parameterType="bvo">
  		update board set title=#{title}, content=#{content}, image_file=#{image_file} where bno=#{bno}
</update>

 


 

== 수정 실행 화면 ==

 





 


== 이미지파일 삭제 (컴퓨터에 저장된 이미지파일) ==

 

--  1번방법 : 파라미터로 값을 보내서 삭제하기 --

 

1. board파일의 detail.jsp에서 삭제버튼 클릭시 ) 파라미터에 image_file이름 추가

- 상세게시판 detail.jsp 추가코드

<a href="/brd/remove?bno=${bvo.bno }&fileName=${bvo.image_file}"><button type="button">삭제</button></a>

- 상세게시판 detail.jsp 전체코드

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<title>detail 상세정보</title>
</head>
<body>
<h3>-- detail 게시판 상세 페이지 --</h3>
	
	<table class="table table-hover">
		<tr>
			<th>번호</th>
			<td>${bvo.bno }</td>
		</tr>
		<tr>
			<th>제목</th>
			<td>${bvo.title }</td>
		</tr>
		<tr>
			<th>사용자</th>
			<td>${bvo.writer }</td>
		</tr>
		<tr>
			<th>내용</th>
			<td>${bvo.content }</td>
		</tr>
		<tr>
			<th>작성일자</th>
			<td>${bvo.reg_date }</td>
		</tr>
		<tr>
			<th>조회수</th>
			<td>${bvo.count }</td>
		</tr>
		<tr>
			<th>첨부파일</th>
			<td>
				<c:if test="${bvo.image_file ne null && bvo.image_file ne ''}">
					<img alt="사진안떠욥" src="/_fileUpload/${bvo.image_file}">
				</c:if>
			</td>
		</tr>
	</table>
	<a href="/brd/modify?bno=${bvo.bno }"><button type="button">수정</button></a>
	<a href="/brd/remove?bno=${bvo.bno }&fileName=${bvo.image_file}"><button type="button">삭제</button></a>
	<a href="/brd/page"><button type="button">리스트로 돌아가기</button></a>
	
	<br><br><hr><br><br>
	
	
	<h3>-- Comment line --</h3><br>
	<!-- 댓글 작성 라인 -->
	<h4>댓글 작성</h4>
	<!-- js로 가져와 사용할 예정이라 id, button type="button" 사용 -->
	<input type="text" id="cmtWriter" value="${ses.id }" placeholder="writer" readonly="readonly"> <br>
	<input type="text" id="cmtText" placeholder="Add Comment">
	<button type="button" id="cmtAddBtn">댓글 등록</button><br>
	</div>
	
	<br><br><hr><br><br>
	
	<!-- 댓글 표시 라인 -->
	<h4>작성된 댓글</h4>
	<div class="accordion accordion-flush" id="accordionFlushExample">
	  	<div class="accordion-item">
		    <h2 class="accordion-header" id="flush-headingOne">
		      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseOne" aria-expanded="false" aria-controls="flush-collapseOne">
		       cno ,writer
		      </button>
		    </h2>
		    <div id="flush-collapseOne" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#accordionFlushExample">
		      <div class="accordion-body">
		      	content, reg_date
		      </div>
		    </div>
	  </div>
  </div>
	
	<script type="text/javascript"> //번호 보내기
	const bnoVal = `<c:out value = "${bvo.bno}" />`;
	</script>
	
	<script src="/resources/board_detail.js"></script>
	<!-- 상단에 번호 보내기 사용가능 -->
	
	<script type="text/javascript">
		printCommentList(bnoVal);
	</script>
	
</html>

 

2.  handle패키지에 FileHandler(class) 생성

package handle;

import java.io.File;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileHandler {
	private static Logger log = LoggerFactory.getLogger(FileHandler.class);
	
	//파일이름과 정보를 받아서 파일을 삭제하는 메서드
	// 리턴타입:int = 삭제되었는지 확인하는 isOk 
	public int deleteFile(String imageFileName, String savePath) {
		
		boolean isDel = false;
		log.info(">>>deleteFile method 접근");
		log.info(">>>imageFileName? : " + imageFileName);
		//파일삭제시 리턴값이 boolean으로 와여
		
		File fileDir = new File(savePath); //경로를 담은 파일
		File removeFile = new File(fileDir + File.separator + imageFileName); 
		File removeThumbFile = new File(fileDir + File.separator + "th_" + imageFileName);
		
		//파일이 있는지(존재하는지) 확인 -> 있으면 삭제
		if(removeFile.exists() || removeThumbFile.exists()) { //있다면
			isDel = removeFile.delete(); //리턴형태 boolean으로 나옴
			log.info(">>> removeFile 값이 삭제되었는가? " + (isDel ? "OK" : "Fail"));
			
			if(isDel) { //removFile이 없어졌다면 removeThumbFile도 삭제
				isDel = removeThumbFile.delete();
				log.info(">>> removeThumbFile 값이 삭제되었는가? " + (isDel ? "OK" : "Fail"));
			}
		}
		
		log.info(">>>FileHandler remove OK! ");
		return isDel? 1 : 0; //true면 1 아니면 0을 리턴
	}

}

 

3. BoardController에서 case "delete"에 파일삭제 코드 작성

case "remove":
			//DB삭제
			int bno = Integer.parseInt(request.getParameter("bno"));
			isOk = bsv.remove(bno);
			log.info(">>> remove " + (isOk > 0 ? "성공" : "실패"));
			
			//저장한 파일 사진 삭제
			savePath = getServletContext().getRealPath("/_fileUpload");
			File fileDir = new File(savePath);
			
			String fileName = request.getParameter("fileName");
			
			FileHandler han = new FileHandler();
			int isOk2 = han.deleteFile(fileName, savePath);	
			log.info(">>> removeFile ?" + (isOk2 > 0 ? "성공" : "실패"));
			
			//이동
			destPage="/brd/page";
			break;

 

--  2번방법 : DB에서 이름을 가져와서 삭제하기 --

 

1. 1번 방법의  2번 - handle패키지에 FileHandler(class) 생성하기

 

2.  BoardController에서 case "delete"에 파일삭제 코드 작성

DB에서 받아오는 경우!

1) bsv.remove(bno);에서 받아오는 리턴값을 bvo 객체로 받아오기
2) 받아온 bvo객체에서 image_file의 이름만 추출해서 String fileName에 저장
3) FileHandler han = new FileHandler();
       int isOk2 = han.deleteFile(fileName, savePath);

 


 

== 삭제 실행 화면 ==

 


DB에서도 삭제되고, 파일에서도 사진이 사라진것을 확인가능!