본문 바로가기
카테고리 없음

게시판 만들기 02. 게시판 글쓰기 구현 + 첨부파일 처리

by 둥바 2022. 9. 6.

 

1. list.jsp에 글쓰기 버튼 추가하고, 제이쿼리와 자바스크립트를 통해 글쓰기 페이지로 이동

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
<script type="text/javascript">
$(function(){
	$("#btnWrite").click(function(){
		//javascript로 이동
		location.href="${path}/board/write.jsp";
	});
});

</script>
</head>
<body>
<h2>게시판</h2>
<button id="btnWrite">글쓰기</button>
<table border="1" style="width: 100%;">
  <tr>
    <th>번호</th>
    <th>이름</th>
    <th>제목</th>
    <th>날짜</th>
    <th>조회수</th>
    <th>첨부파일</th>
    <th>파일사이즈</th>
    <th>다운로드</th>
    <th>IP주소</th>
  </tr>
<c:forEach var="dto" items="${list}">  
  <tr>
    <td>${dto.num}</td>
    <td>${dto.writer}</td>
    <td>${dto.subject}</td>
    <td>${dto.reg_date}</td>
    <td>${dto.readcount}</td>
    <td>${dto.filename}</td>
    <td>${dto.filesize}</td>
    <td>${dto.down}</td>
    <td>${dto.ip}</td>
  </tr>
</c:forEach>  
</table>
</body>
</html>

 

2. 글쓰기 페이지 작성

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>글쓰기 페이지</title>
<%@ include file="../include/header.jsp" %>
<script src="../include/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
	$("#btnSave").click(function() {
		var writer=$("#writer").val();
		var subject=$("#subject").val();
		var content=$("#content").val();
		var passwd=$("#passwd").val();
		if(writer==""){
			alert("이름을 입력하세요.");
			$("#writer").focus();
			return;
		}
		if(subject==""){
			alert("제목을 입력하세요.");
			$("#subject").focus();
			return;
		}
		if(content==""){
			alert("내용을 입력하세요.");
			$("#content").focus();
			return;
		}
		if(passwd==""){
			alert("비밀번호를 입력하세요.");
			$("#passwd").focus();
			return;
		}
		document.form1.submit();
	});
});

</script>


</head>
<body>
<h2>글쓰기</h2>
<form name="form1" method="post" action="${path}/board_servlet/insert.do">
<table>
 <tr>
  <td>이름</td>
  <td><input name="writer" id="writer"> </td>
 </tr>
 <tr>
  <td>제목</td>
  <td><input name="subject" id="subject" size="60"> </td>
 </tr>
 <tr>
  <td>본문</td>
  <td><textarea rows="5" cols="60" name="content" id="content"></textarea> </td>
 </tr>
 <tr>
  <td>첨부파일</td>
  <td><input type="file" name="file1"> </td>
 </tr>
 <tr>
  <td>비밀번호</td>
  <td><input type="password" name="passwd" id="passwd"> </td>
 </tr>
 <tr>
  <td colspan="2" align="center">
   <input type="button" value="확인" id="btnSave">
  </td>
 </tr>
</table>

</form>
</body>
</html>

 

3. insert.do 요청이 들어왔을 때 처리

 

package board;

import java.io.IOException;
import java.net.InetAddress;
import java.util.List;

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

import board.dao.BoardDAO;
import board.dto.BoardDTO;



public class BoardController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		BoardDAO dao = new BoardDAO();
		if(url.indexOf("list.do")!=-1) {
			List<BoardDTO> list=dao.list();
			request.setAttribute("list", list);
			String page="/board/list.jsp";
			RequestDispatcher rd=request.getRequestDispatcher(page);
			rd.forward(request, response);
		}else if(url.indexOf("insert.do")!=-1) {
			String writer = request.getParameter("writer");
			String subject = request.getParameter("subject");
			String content = request.getParameter("content");
			String passwd = request.getParameter("passwd");
			//클라이언트의 ip주소 가져오기
			String ip = request.getRemoteAddr();
			if(ip.equalsIgnoreCase("0:0:0:0:0:0:0:1:")) {
				InetAddress inetAddress = InetAddress.getLocalHost();
				ip = inetAddress.getHostAddress();
			}
			System.out.println("클라이언트의 ip 주소 :" + ip);
			String filename=" ";
			int filesize=0;
			BoardDTO dto = new BoardDTO();
			dto.setWriter(writer);
			dto.setSubject(subject);
			dto.setContent(content);
			dto.setPasswd(passwd);
			dto.setIp(ip);
			dto.setFilename(filename);
			dto.setFilesize(filesize);
			
			dao.insert(dto);
			//넣은 다음에는 list 새로고침
			String page = "/board_servlet/list.do";
			//리다이렉트 처리
			response.sendRedirect(contextPath+page);
		}
		
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

4. dao에서 insert 처리

package board.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import board.dto.BoardDTO;
import sqlmap.MybatisManager;

public class BoardDAO {

	//게시물 목록 리스트
	public List<BoardDTO> list(){
		List<BoardDTO> list = null;
		SqlSession session = null;
		
		try {
			session = MybatisManager.getInstance().openSession();
			list = session.selectList("board.list");//네임스페이스.아이디
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		return list;
	}

	public void insert(BoardDTO dto) {
		SqlSession session = null;	
		try {
			session = MybatisManager.getInstance().openSession();
			session.insert("board.insert", dto);
			session.commit();//데이터가 변경 시에는 커밋
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		
	}
}

 

5. xml에서 board.insert처리

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="board">
<select id="list" resultType="board.dto.BoardDTO"> 
select num,writer,subject,reg_date,readcount,filename,filesize,down,ip 
from board 
order by num desc </select>

<insert id="insert">
insert into board
	(num,writer,subject,passwd,ref,re_step,re_level,content,ip,filename,filesize) 
	values
	( (select nvl(max(num)+1,1) from board)
	  ,#{writer},#{subject},#{passwd}
	  ,(select nvl(max(num)+1,1) from board)
	  ,1,0,#{content},#{ip},#{filename},#{filesize})

</insert>


</mapper>

 

index.jsp를 실행시켜보니, 게시글을 추가할 수 있었다.

결과)


첨푸파일 기능 처리

 

1. 기존 write.jsp의 form 태그속성에 enctype="multipart/form-data"를 추가해준다.(파일 업로드 위함)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>글쓰기 페이지</title>
<%@ include file="../include/header.jsp" %>
<script src="../include/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(function() {
	$("#btnSave").click(function() {
		var writer=$("#writer").val();
		var subject=$("#subject").val();
		var content=$("#content").val();
		var passwd=$("#passwd").val();
		if(writer==""){
			alert("이름을 입력하세요.");
			$("#writer").focus();
			return;
		}
		if(subject==""){
			alert("제목을 입력하세요.");
			$("#subject").focus();
			return;
		}
		if(content==""){
			alert("내용을 입력하세요.");
			$("#content").focus();
			return;
		}
		if(passwd==""){
			alert("비밀번호를 입력하세요.");
			$("#passwd").focus();
			return;
		}
		document.form1.submit();
	});
});

</script>


</head>
<body>
<h2>글쓰기</h2>
<form name="form1" method="post" 
enctype="multipart/form-data"
action="${path}/board_servlet/insert.do">
<table>
 <tr>
  <td>이름</td>
  <td><input name="writer" id="writer"> </td>
 </tr>
 <tr>
  <td>제목</td>
  <td><input name="subject" id="subject" size="60"> </td>
 </tr>
 <tr>
  <td>본문</td>
  <td><textarea rows="5" cols="60" name="content" id="content"></textarea> </td>
 </tr>
 <tr>
  <td>첨부파일</td>
  <td><input type="file" name="file1"> </td>
 </tr>
 <tr>
  <td>비밀번호</td>
  <td><input type="password" name="passwd" id="passwd"> </td>
 </tr>
 <tr>
  <td colspan="2" align="center">
   <input type="button" value="확인" id="btnSave">
  </td>
 </tr>
</table>

</form>
</body>
</html>

 

multipart는 request 객체를 확장한 것이므로,

 

2. 서블릿에서 수정

package board;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Enumeration;
import java.util.List;

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

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

import board.dao.BoardDAO;
import board.dto.BoardDTO;
import common.Constants;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;


public class BoardController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		BoardDAO dao = new BoardDAO();
		if(url.indexOf("list.do")!=-1) {
			List<BoardDTO> list=dao.list();
			request.setAttribute("list", list);
			String page="/board/list.jsp";
			RequestDispatcher rd=request.getRequestDispatcher(page);
			rd.forward(request, response);
		}else if(url.indexOf("insert.do")!=-1) {
			//파일업로드 처리
			File uploadDir = new File(Constants.UPLOAD_PATH);
			if(!uploadDir.exists()) {//업로드 디렉토리가 존재하지 않는다면
				uploadDir.mkdir();//디렉토리 생성
			}
			//request를 확장시킨 MultipartRequest 생성
			//new MultipartRequest(request,"업로드디렉토리",제한용량,"인코딩",파일명중복방지처리옵션)
			MultipartRequest multi=new MultipartRequest(request, Constants.UPLOAD_PATH, 
					Constants.MAX_UPLOAD, "utf-8", new DefaultFileRenamePolicy());
			
			String writer = multi.getParameter("writer");
			String subject = multi.getParameter("subject");
			String content = multi.getParameter("content");
			String passwd = multi.getParameter("passwd");
			//클라이언트의 ip주소 가져오기
			String ip = request.getRemoteAddr();
			if(ip.equalsIgnoreCase("0:0:0:0:0:0:0:1:")) {
				InetAddress inetAddress = InetAddress.getLocalHost();
				ip = inetAddress.getHostAddress();
			}
			System.out.println("클라이언트의 ip 주소 :" + ip);
			String filename=" ";
			int filesize=0;
			try {
				//첨부파일 집합
				Enumeration files = multi.getFileNames();
				//다음요소가 있으면
				while(files.hasMoreElements()) {
					String file1 = (String)files.nextElement();
					filename = multi.getFilesystemName(file1);
					File f1=multi.getFile(file1);
					if(f1 != null) {
						filesize=(int)f1.length();
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			
			BoardDTO dto = new BoardDTO();
			dto.setWriter(writer);
			dto.setSubject(subject);
			dto.setContent(content);
			dto.setPasswd(passwd);
			dto.setIp(ip);
			//파일 첨부를 하지 않을 경우
			if(filename == null || filename.trim().equals("")) {
				//빈문자열,아예 널값
				filename = "-";
			}
			
			
			
			dto.setFilename(filename);
			dto.setFilesize(filesize);
			
			dao.insert(dto);
			//넣은 다음에는 list 새로고침
			String page = "/board_servlet/list.do";
			//리다이렉트 처리
			response.sendRedirect(contextPath+page);
		}
		
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

MultipartRequest클래스는 파일업로드를 담당하는 클래스이다.

MultipartRequest클래스의 생성자는 다음과 같다.

MultipartRequest(request,파일 업로드 경로,최대 용량,인코딩,파일명중복처리방지옵션);

 

- 파일 업로드 처리를 위해서 실제 업로드할 디렉토리가 존재하는지 파일 클래스로 확인

File uploadDir = new File(업로드 경로);

if(!uploadDir.exists()){ 업로드 디렉토리가 없다면,

uploadDir.mkdir(); //업로드 디렉토리를 먼저 생성

}

 

-그 이후에 

filename과 filesize를 가져오기 위해서,

try-catch문 안에 MultipartRequest 클래스의 객체인 multi를 활용

multi.getFileNames() 는 파일이 여러 개 업로드 된 경우 타입이 file인 파라미터의 이름을 enumeration 형태로 반환한다.

Enumeration files = multi.getFileNames(); //업로드 된 파일의 이름을 Enumeartion으로 반환
while(files.hasMoreNext()){ //Enumeration 요소가 있으면 true
String file1 = (String)files.nextElement(); //Enumeratino 내의 다음 요소 반환(Object)
String filename = multi.getFilesystemName(file1); //1.서버에 실제로 업로드 된 파일의 이름을 반환
File f1 = multi.getFile(file1); //2.실제 업로드 된 파일 객체 자체를 반환
if(f1 != null){ //존재한다면
filesize = (int)f1.length(); //3.파일의 실제 크기
}

 

3. 파일 이름이 길면 불편하므로, 이미지화 시켜서 바꾸기

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
<script type="text/javascript">
$(function(){
	$("#btnWrite").click(function(){
		//javascript로 이동
		location.href="${path}/board/write.jsp";
	});
});

</script>
</head>
<body>
<h2>게시판</h2>
<button id="btnWrite">글쓰기</button>
<table border="1" style="width: 100%;">
  <tr>
    <th>번호</th>
    <th>이름</th>
    <th>제목</th>
    <th>날짜</th>
    <th>조회수</th>
    <th>첨부파일</th>
    <th>파일사이즈</th>
    <th>다운로드</th>
    <th>IP주소</th>
  </tr>
<c:forEach var="dto" items="${list}">  
  <tr>
    <td>${dto.num}</td>
    <td>${dto.writer}</td>
    <td>${dto.subject}</td>
    <td>${dto.reg_date}</td>
    <td>${dto.readcount}</td>
    <td align="center">
    	<c:if test="${dto.filesize > 0}">
    		<img src="../images/file.gif">
    	</c:if>
    </td>

    <td>${dto.filesize}</td>
    <td>${dto.down}</td>
    <td>${dto.ip}</td>
  </tr>
</c:forEach>  
</table>
</body>
</html>

- 파일 사이즈가 0보다 크다면, 이미지

 

4. 파일 다운로드 기능 추가 

 

- view 단에서 일단 클릭할 수 있게 앵커 달아주기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
<script type="text/javascript">
$(function(){
	$("#btnWrite").click(function(){
		//javascript로 이동
		location.href="${path}/board/write.jsp";
	});
});

</script>
</head>
<body>
<h2>게시판</h2>
<button id="btnWrite">글쓰기</button>
<table border="1" style="width: 100%;">
  <tr>
    <th>번호</th>
    <th>이름</th>
    <th>제목</th>
    <th>날짜</th>
    <th>조회수</th>
    <th>첨부파일</th>
    <th>파일사이즈</th>
    <th>다운로드</th>
    <th>IP주소</th>
  </tr>
<c:forEach var="dto" items="${list}">  
  <tr>
    <td>${dto.num}</td>
    <td>${dto.writer}</td>
    <td>${dto.subject}</td>
    <td>${dto.reg_date}</td>
    <td>${dto.readcount}</td>
    <td align="center">
    	<c:if test="${dto.filesize > 0}">
	    	<a href="${path}/board_servlet/download.do?num=${dto.num}">
	    		<img src="../images/file.gif">
	    	</a>
    	</c:if>
    </td>

    <td>${dto.filesize}</td>
    <td>${dto.down}</td>
    <td>${dto.ip}</td>
  </tr>
</c:forEach>  
</table>
</body>
</html>

 

- download.do로 요청하는데, 몇 번째 게시글인지도 같이 가야하므로 쿼리스트링 타입으로 보냄

 

5. servlet으로 이동해서

		}else if(url.indexOf("download.do")!=-1) {
			int num = Integer.parseInt(request.getParameter("num"));
			//파일 이름
			String filename = dao.getFileName(num);
			System.out.println("첨부 파일 이름 :" + filename);
		}	
	}

까지 만들고 dao로 이동

 

6. dao.getFileName(num) 메소드 생성

package board.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import board.dto.BoardDTO;
import sqlmap.MybatisManager;

public class BoardDAO {

	//게시물 목록 리스트
	public List<BoardDTO> list(){
		List<BoardDTO> list = null;
		SqlSession session = null;
		
		try {
			session = MybatisManager.getInstance().openSession();
			list = session.selectList("board.list");//네임스페이스.아이디
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		return list;
	}

	public void insert(BoardDTO dto) {
		SqlSession session = null;	
		try {
			session = MybatisManager.getInstance().openSession();
			session.insert("board.insert", dto);
			session.commit();//데이터가 변경 시에는 커밋
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		
	}
	//첨부파일 이름 찾기
	public String getFileName(int num) {
		String result = "";
		SqlSession session = null;
		
		try {
			session = MybatisManager.getInstance().openSession();
			result = session.selectOne("board.getFileName",num); //하나의 객체만 리턴
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		return result;
	}
}

 

7. 매핑처리

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="board">
<select id="list" resultType="board.dto.BoardDTO"> 
select num,writer,subject,reg_date,readcount,filename,filesize,down,ip 
from board 
order by num desc </select>

<insert id="insert">
insert into board
	(num,writer,subject,passwd,ref,re_step,re_level,content,ip,filename,filesize) 
	values
	( (select nvl(max(num)+1,1) from board)
	  ,#{writer},#{subject},#{passwd}
	  ,(select nvl(max(num)+1,1) from board)
	  ,1,0,#{content},#{ip},#{filename},#{filesize})

</insert>

 <select id="getFileName" resultType="String">
  select filename
	from board
	where num=#{num}
 </select>


</mapper>

 

8.  (다운 기능 구현)

서버 : 파일을 클라이언트에게 보내는 것

(파일을 InputStream으로 읽어서 OutputStream으로 클라이언트에게 쓰기)

package board;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

import board.dao.BoardDAO;
import board.dto.BoardDTO;
import common.Constants;


public class BoardController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = request.getRequestURL().toString();
		String contextPath = request.getContextPath();
		BoardDAO dao = new BoardDAO();
		if(url.indexOf("list.do")!=-1) {
			List<BoardDTO> list=dao.list();
			request.setAttribute("list", list);
			String page="/board/list.jsp";
			RequestDispatcher rd=request.getRequestDispatcher(page);
			rd.forward(request, response);
		}else if(url.indexOf("insert.do")!=-1) {
			//파일업로드 처리
			File uploadDir = new File(Constants.UPLOAD_PATH);
			if(!uploadDir.exists()) {//업로드 디렉토리가 존재하지 않는다면
				uploadDir.mkdir();//디렉토리 생성
			}
			//request를 확장시킨 MultipartRequest 생성
			//new MultipartRequest(request,"업로드디렉토리",제한용량,"인코딩",파일명중복방지처리옵션)
			MultipartRequest multi=new MultipartRequest(request, Constants.UPLOAD_PATH, 
					Constants.MAX_UPLOAD, "utf-8", new DefaultFileRenamePolicy());
			
			String writer = multi.getParameter("writer");
			String subject = multi.getParameter("subject");
			String content = multi.getParameter("content");
			String passwd = multi.getParameter("passwd");
			//클라이언트의 ip주소 가져오기
			String ip = request.getRemoteAddr();
			if(ip.equalsIgnoreCase("0:0:0:0:0:0:0:1:")) {
				InetAddress inetAddress = InetAddress.getLocalHost();
				ip = inetAddress.getHostAddress();
			}
			System.out.println("클라이언트의 ip 주소 :" + ip);
			String filename=" ";
			int filesize=0;
			try {
				//첨부파일 집합
				Enumeration files = multi.getFileNames();
				//다음요소가 있으면
				while(files.hasMoreElements()) {
					String file1 = (String)files.nextElement();
					filename = multi.getFilesystemName(file1);
					File f1=multi.getFile(file1);
					if(f1 != null) {
						filesize=(int)f1.length();
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			
			BoardDTO dto = new BoardDTO();
			dto.setWriter(writer);
			dto.setSubject(subject);
			dto.setContent(content);
			dto.setPasswd(passwd);
			dto.setIp(ip);
			//파일 첨부를 하지 않을 경우
			if(filename == null || filename.trim().equals("")) {
				//빈문자열,아예 널값
				filename = "-";
			}
			
			
			
			dto.setFilename(filename);
			dto.setFilesize(filesize);
			
			dao.insert(dto);
			//넣은 다음에는 list 새로고침
			String page = "/board_servlet/list.do";
			//리다이렉트 처리
			response.sendRedirect(contextPath+page);
		}else if(url.indexOf("download.do")!=-1) {
			int num = Integer.parseInt(request.getParameter("num"));
			//파일 이름
			String filename = dao.getFileName(num);
			System.out.println("첨부 파일 이름 :" + filename);
			//업로드되었던 파일의 위치정보값을 path에 저장
			String path=Constants.UPLOAD_PATH+filename;
			//파일 입출력(바이트 처리)
			byte b[] = new byte[4096]; //바이트배열
			//업로드 폴더에 저장된 파일을 읽기 위한 스트림 생성
			FileInputStream fis = new FileInputStream(path);
			//mimeType : (파일의 종류 - img,mp3,txt 등..)
			String mimeType=getServletContext().getMimeType(path);
			//스트림 방식의 파일 다운로드시 한글 파일명 관련 브라우저 헤더 처리(utf-8)
			//octet-stream : 8비트로 된 일련의 데이터를 뜻하며 모든 종류의 이진데이터 처리
            if(mimeType==null) {
				mimeType = "application/octet-stream;charset=utf-8";
			}
            //파일 이름에 한글이 포함된 경우 header로 값을 보내는데 header에는
            //한글, 특수문자가 올 수 없기 때문에 톰캣서버의 기본셋팅 언어인 서유럽언어를
            //한글처리가 가능한 utf-8로 인코딩처리해야한다.
            filename = new String(filename.getBytes("utf-8"),"8859_1");
			response.setHeader("Content-Disposition", "attachment;filename="+filename);
			//OutpustStream생성(서버에서 클라이언트에 쓰기)
			ServletOutputStream out = response.getOutputStream();
			int numRead;
			while(true) {
				numRead = fis.read(b, 0, b.length);//데이터 읽음
				if(numRead == -1) break; //내용이 없으면 빠져나감
				out.write(b, 0, numRead);//데이터 쓰기
			}
			//리소스 정리
			out.flush();
			out.close();
			fis.close();
		
		
		}
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

여기서 filename = new String(filename.getBytes("utf-8"),"8859_1"); 의 경우는

String인 filename을 utf-8의 캐릭터셋으로 바이트배열로 변환한 뒤,

"8859_1"로 String을 다시 생성하여 디코딩하는 과정이다.

new String(filename.getByte("변환할 인코딩"),"기본인코딩");

 

 


다운로드 횟수 증가 처리 구현

 

1.dao.plusDown(num) 메소드를  작성한 뒤, dao에서 메소드 생성

package board.dao;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import board.dto.BoardDTO;
import sqlmap.MybatisManager;

public class BoardDAO {

	//게시물 목록 리스트
	public List<BoardDTO> list(){
		List<BoardDTO> list = null;
		SqlSession session = null;
		
		try {
			session = MybatisManager.getInstance().openSession();
			list = session.selectList("board.list");//네임스페이스.아이디
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		return list;
	}

	public void insert(BoardDTO dto) {
		SqlSession session = null;	
		try {
			session = MybatisManager.getInstance().openSession();
			session.insert("board.insert", dto);
			session.commit();//데이터가 변경 시에는 커밋
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		
	}
	//첨부파일 이름 찾기
	public String getFileName(int num) {
		String result = "";
		SqlSession session = null;
		
		try {
			session = MybatisManager.getInstance().openSession();
			result = session.selectOne("board.getFileName",num); //하나의 객체만 리턴
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		return result;
	}
	//다운로드 회수 증가 처리
	public void plusDown(int num) {
		SqlSession session = null;
		try {
			session=MybatisManager.getInstance().openSession();
			session.update("board.plusDown",num);
			session.commit();//데이터가 변경 시에는 커밋
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(session!=null) session.close();
		}
		
		
	}
}

 

2. xml에서 작성

<update id="plusDown">
update board set down=down+1 where num=#{num}
</update>

 

3. 다운로드  회수 1초마다 리로드

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Insert title here</title>
<%@ include file="../include/header.jsp" %>
<script type="text/javascript">
$(function(){
	$("#btnWrite").click(function(){
		//javascript로 이동
		location.href="${path}/board/write.jsp";
	});
});

</script>
</head>
<body>
<h2>게시판</h2>
<button id="btnWrite">글쓰기</button>
<table border="1" style="width: 100%;">
  <tr>
    <th>번호</th>
    <th>이름</th>
    <th>제목</th>
    <th>날짜</th>
    <th>조회수</th>
    <th>첨부파일</th>
    <th>파일사이즈</th>
    <th>다운로드</th>
    <th>IP주소</th>
  </tr>
<c:forEach var="dto" items="${list}">  
  <tr>
    <td>${dto.num}</td>
    <td>${dto.writer}</td>
    <td>${dto.subject}</td>
    <td>${dto.reg_date}</td>
    <td>${dto.readcount}</td>
    <td align="center">
    	<c:if test="${dto.filesize > 0}">
	    	<a href="${path}/board_servlet/download.do?num=${dto.num}">
	    		<img src="../images/file.gif">
	    	</a>
	    	<script>
	    	setTimeout('location.reload()',1000); //다운로드 회수를 1초마다 새로고침
	    	
	    	</script>
    	</c:if>
    </td>

    <td>${dto.filesize}</td>
    <td>${dto.down}</td>
    <td>${dto.ip}</td>
  </tr>
</c:forEach>  
</table>
</body>
</html>

 

 

잘 처리되는 것을 확인할 수 있다.