Dev/JSP & Servlet

cos.jar를 이용한 파일 업로드(2)-파일 업로드,다운로드.삭제

창문닦이 2019. 3. 4. 18:29

DB를 이용한 파일업로드 개념

파일 정보를 저장할 테이블 생성

create table fileTest

(num number(7) primary key,

subject varchar2(50) not null,

saveFileName varchar2(50),

originalFileName varchar2(50));

서블릿 매핑 web.xml 설정

<!-- Servlet 파일 업로드 -->

<servlet>

<servlet-name>fileTestServlet</servlet-name>

<servlet-class>com.fileTest.FileTestServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>fileTestServlet</servlet-name>

<url-pattern>/file/*</url-pattern>

</servlet-mapping>


FileTestDTO 생성 

package com.file;

public class FileTestDTO {

private int num;

private String subject;

private String saveFileName;

private String originalFileName;

//getter,setter생성

}

FileTestDAO 생성

파일 데이터는 수정이 필요 없으므로 update문은 사용하지 않음(등록,삭제,조회만 진행)

public class FileTestDAO {

private Connection conn = null;

public FileTestDAO(Connection conn){

this.conn = conn;

}

//레코드 번호

public int getMaxNum(){

int maxNum = 0;

PreparedStatement pstmt = null;

ResultSet rs = null;

String sql;

try {

sql = "select nvl(max(num),0) from fileTest";

pstmt = conn.prepareStatement(sql);

rs = pstmt.executeQuery();

if(rs.next()){

maxNum = rs.getInt(1);

}

rs.close();

pstmt.close();

} catch (Exception e) {

System.out.println(e.toString());

}

return maxNum;

}



//파일데이터 입력

public void insertData(FileTestDTO dto){

PreparedStatement pstmt = null;

String sql;

try {

sql = "insert into fileTest (num,subject,saveFileName, ";

sql += "originalFileName) values (?,?,?,?)";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, dto.getNum());

pstmt.setString(2, dto.getSubject());

pstmt.setString(3, dto.getSaveFileName());

pstmt.setString(4, dto.getOriginalFileName());

pstmt.executeUpdate();

pstmt.close();

} catch (Exception e) {

System.out.println(e.toString());

}

}



//파일데이터 전체조회

public List<FileTestDTO> getList(int start, int end){

List<FileTestDTO> lists = new ArrayList<FileTestDTO>();

PreparedStatement pstmt = null;

ResultSet rs = null;

String sql;

try {

sql = "select * from (select rownum rnum,num,subject,saveFileName,originalFileName ";

sql += "from fileTest order by num desc) ";

sql += "where rnum >= ? and rnum <=? ";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, start);

pstmt.setInt(2, end);

rs = pstmt.executeQuery();

while(rs.next()){

FileTestDTO dto = new FileTestDTO();

dto.setNum(rs.getInt("num"));

dto.setSubject(rs.getString("subject"));

dto.setSaveFileName(rs.getString("saveFileName"));

dto.setOriginalFileName(rs.getString("originalFileName"));

lists.add(dto);

}

rs.close();

pstmt.close();

} catch (Exception e) {

System.out.println(e.toString());

}

return lists;

}



//특정 데이터 조회

public FileTestDTO getReadData(int num){

FileTestDTO dto = null;

PreparedStatement pstmt = null;

ResultSet rs = null;

String sql;

try {

sql = "select num,subject,saveFileName,originalFileName ";

sql += "from fileTest where num = ? ";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, num); //매개변수로 받은 num. where조건에 넣어줌

rs = pstmt.executeQuery();

if(rs.next()){

dto = new FileTestDTO();

dto.setNum(rs.getInt("num"));

dto.setSubject(rs.getString("subject"));

dto.setSaveFileName(rs.getString("saveFileName"));

dto.setOriginalFileName(rs.getString("originalFileName"));

}

rs.close();

pstmt.close();

} catch (Exception e) {

System.out.println(e.toString());

}

return dto;

}



//파일데이터 삭제

public void deleteData(int num){

PreparedStatement pstmt = null;

String sql;

try {

sql = "delete fileTest where num=?";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1,num);

pstmt.executeUpdate();

pstmt.close();

} catch (Exception e) {

System.out.println(e.toString());

}

}



//데이터 카운트

public int getDataCount(){

int totalDataCount = 0;

PreparedStatement pstmt =null;

ResultSet rs = null;

String sql;

try {

sql = "select nvl(count(*),0) from fileTest ";

pstmt= conn.prepareStatement(sql);

rs = pstmt.executeQuery();

if(rs.next())

totalDataCount = rs.getInt(1);

rs.close();

pstmt.close();

} catch (Exception e) {

System.out.println(e.toString());

}

return totalDataCount;

}

}


FileTestServlet 서블릿 클래스 생성

public class FileTestServlet extends HttpServlet{

private static final long serialVersionUID = 1L;

protected void forward(HttpServletRequest req, HttpServletResponse resp, String url)

throws ServletException, IOException {

//포워드

RequestDispatcher rd = req.getRequestDispatcher(url);

rd.forward(req, resp);

}

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException {

//dopost 메소드 호출

doPost(req, resp);

}



@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException {

req.setCharacterEncoding("UTF-8");

Connection conn = DBCPConn.getConnection();

FileTestDAO dao = new FileTestDAO(conn);

//페이징 처리

MyUtil myUtil = new MyUtil();

String cp = req.getContextPath();

String uri = req.getRequestURI();

String url;

//파일 업로드 위치 지정

String root = getServletContext().getRealPath("/") ;

String path = root + File.separator + "pds" + File.separator + "saveFile";//File.separator를 역슬래시로 입력해도 가능


//해당경로에 있는 파일로 객체 생성

File f = new File(path);

//파일 존재하지 않으면 디렉토리 생성

if(!f.exists()){

f.mkdirs();

}

if(uri.indexOf("write.do")!=-1){


//파일업로드 페이지 호출

url = "/fileTest/write.jsp";

forward(req, resp, url);

}else if(uri.indexOf("write_ok.do")!=-1){

//파일업로드 페이지 호출(DAO실행)

String encType = "UTF-8";

int maxSize = 10*1024*1024;


//물리적 파일 업로드 (cos.lib의 MultipartRequest 사용 )

MultipartRequest mr = new MultipartRequest(req, path, maxSize, encType, new DefaultFileRenamePolicy());

//DB에 파일정보 입력

//업로드한 파일로부터 정보 추출

if(mr.getFile("uploadFile")!=null){//null이 아니면 파일이 제대로 업로드된것

FileTestDTO dto = new FileTestDTO();

int maxNum = dao.getMaxNum();

dto.setNum(maxNum+1);

dto.setSubject(mr.getParameter("subject"));

dto.setSaveFileName(mr.getFilesystemName("uploadFile"));

dto.setOriginalFileName(mr.getOriginalFileName("uploadFile"));

dao.insertData(dto);

}

//list.do 페이지로 리다이렉트

url = cp + "/file/list.do";

resp.sendRedirect(url);

}else if(uri.indexOf("list.do")!=-1){

//파일업로드 내역 조회 페이지 호출(DAO실행)

String pageNum = req.getParameter("pageNum");

int currentPage = 1; //처음 띄우는 리스트 페이지

if(pageNum!=null){

currentPage = Integer.parseInt(pageNum);

}

int dataCount = dao.getDataCount();

int numPerPage = 5;

int totalPage = myUtil.getPageCount(numPerPage, dataCount);

if(currentPage>totalPage)

currentPage = totalPage;

int start = (currentPage-1)*numPerPage+1;

int end = currentPage*numPerPage;

String listUrl = cp+"/file/list.do";

List<FileTestDTO> lists = dao.getList(start,end);

String pageIndexList = myUtil.pageIndexList(currentPage, totalPage, listUrl);

//다운로드경로

String downloadPath = cp + "/file/download.do";

//삭제경로

String deletePath = cp + "/file/delete.do";

//파일정보 테이블을 리스트로 전달

req.setAttribute("lists", lists);

req.setAttribute("pageNum", pageNum);

req.setAttribute("downloadPath", downloadPath);

req.setAttribute("deletePath", deletePath);

req.setAttribute("pageIndexList", pageIndexList);

//list.jsp 페이지로 포워드

url = "/fileTest/list.jsp";

forward(req, resp, url);

}else if(uri.indexOf("download.do")!=-1){

//파일 다운로드

int num = Integer.parseInt(req.getParameter("num"));

FileTestDTO dto = dao.getReadData(num);

if(dto==null)

return;//다운로드할 파일이 없으면 종료

//파일을 정상적으로 받으면 true, 아닐경우 false

boolean flag = FileManager.doFileDownload(resp, dto.getSaveFileName(), dto.getOriginalFileName(), path);

//물리적 파일은 지웠는데 DB상의 정보에서는 삭제되지 않은 경우와 같이

//두 데이터가 자동으로 동기화가 되지 않는 문제가 있음. 그래서 boolean 이용

//다운로드 오류 발생시 flag에 false 반환. 이 때, 오류 메세지 출력

if(flag==false){

resp.setContentType("text/html;charset=utf-8");

PrintWriter out = resp.getWriter();

out.print("<script type='text/javascript'>");

out.print("alert('download error');");

out.print("history.back()");//확인버튼을 누르면 이전화면으로 돌려줌

out.print("</script>");

}

}else if(uri.indexOf("delete.do")!=-1){

int num = Integer.parseInt(req.getParameter("num"));

int pageNum = Integer.parseInt(req.getParameter("pageNum"));

FileTestDTO dto = dao.getReadData(num);

//물리적 파일 삭제

FileManager.doFileDelete(dto.getSaveFileName(), path);

//테이블 정보 삭제

dao.deleteData(num);

//삭제 진행 후 리스트 페이지로 리다이렉트

url = cp + "/file/list.do?pageNum="+pageNum;

resp.sendRedirect(url);

}

}

}


FileManager (물리적 파일 등록/삭제할 클래스)

public class FileManager {

파일다운로드

saveFileName : 서버에 저장된 파일명

originalFileName : 클라이언트가 업로드한 파일명

path : 서버에 저장된 실제 경로

서버에 있는 파일을 읽어서 클라이언트에게 내려보내는 것이기 때문에 req가 아니라 resp가 매개변수로 사용

//파일업로드

public static boolean doFileDownload(HttpServletResponse response, String saveFileName, String originalFileName, String path){

try {

//파일경로

String filePath = path + File.separator + saveFileName ;

//클라이언트가 설정한 파일명이 없을경우 서버에 저장된 파일명으로 입력

if(originalFileName==null || originalFileName.equals("")){

originalFileName = saveFileName;

}

//파일을 다운받아 클라이언트 컴에 파일이름 생성시 한글깨짐 방지

originalFileName = new String(originalFileName.getBytes("euc-kr"),"ISO-8859-1");

File f = new File(filePath);

if(!f.exists()){

return false; //파일이 존재하지 않으면 stop

}

//파일의 종류. ContentType 을 설정

response.setContentType("application/octet-stream");// .txt 와 같이 파일확장자 앞에 붙는 .을 octet-stream라고 함

//헤더정보

response.setHeader("Content-disposition", "attachment;fileName="+originalFileName);

//서버에서 클라이언트로 내려보낼 때, Fileinputstream으로 파일을 읽은 후 bis에 넣은 것

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));//f로 줘도 되고 filepath로 줘도 됨

//읽은 파일을 내보낼 때 outputstream 사용

OutputStream out = response.getOutputStream();

int data;

byte bytes[] = new byte[4096];

while((data=bis.read(bytes,0,4096))!=-1){

out.write(bytes,0,data);

}


out.flush();

out.close();

bis.close();

} catch (Exception e) {

System.out.println(e.toString());

return false;

}

return true;

}



//파일삭제

public static void doFileDelete(String fileName, String path){

try {

String filePath = path + File.separator + fileName;

File f = new File(filePath);

//파일의 경로를 찾아가서 존재할 경우 삭제

if(f.exists()){

f.delete();//물리적 파일삭제

}

} catch (Exception e) {

System.out.println(e.toString());

}

}

}


파일업로드 페이지 write.jsp

<%@ page contentType="text/html; charset=UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%

request.setCharacterEncoding("UTF-8");

String cp = request.getContextPath();

%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

<form action="<%=cp%>/file/write_ok.do" method="post" enctype="multipart/form-data">

제목: <input type="text" name="subject"/><br/>

파일: <input type="file" name="uploadFile"/><br/>

<input type="submit" value="전송"/><br/>

</form>

</body>

</html>



파일 목록 조회 페이지 list.jsp

<%@ page contentType="text/html; charset=UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%

request.setCharacterEncoding("UTF-8");

String cp = request.getContextPath();

%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>파일 목록</title>

</head>

<body>

<br/><br/>

<table width="500" align="center" >

<tr>

<td align="right" colspan="4">

<input type="button" value="글쓰기" onclick="javascript:location='<%=cp%>/file/write.do';"/>

</td>

</tr>

<tr>

<td align="center" width="50">번호</td>

<td align="left" width="150">제목</td>

<td align="left" width="250">파일</td>

<td align="center" width="50">삭제</td>

</tr>

<c:forEach var="dto" items="${lists }">

<tr>

<td align="center" width="50">${dto.num }</td>

<td align="left" width="150">${dto.subject }</td>

<td align="left" width="250">

<a href="${downloadPath }?num=${dto.num }">

${dto.originalFileName }</a></td>

<td align="center" width="50">

<a href="${deletePath}?num=${dto.num }&pageNum=${pageNum }">삭제</a></td>

</tr>

</c:forEach>

<tr>

<td align="center" colspan="4">

<c:if test="${dataCount!=0 }">

${pageIndexList }

</c:if>

<c:if test="${dataCount==0 }">

등록된 파일이 없습니다

</c:if>

</td>

</tr>

</table>

</body>

</html>


batch 파일을 이용한 Tomcat Server 시작 

1. webapps 위치로 .war 파일 export

경로 : D:\java\apache-tomcat-7.0.92\webapps


2. 이클립스에서 설정해놓은 resource 관련 코드가 적용이 되어있지 않은것을 확인할 수 있음.


이클립스에 등록된 내용이 자동으로 동기화가 되지않는다. 복사해서 txt 파일로 편집하여 반영.


3. 이클립스를 실행하지 않더라도 서버 shutdown, startup 킬수있음

경로 D:\java\apache-tomcat-7.0.92\bin


파일 업로드 위치 지정

String root = getServletContext().getRealPath("/") ;

String path = root + File.separator + "pds" + File.separator + "saveFile"; //File.separator를 역슬래시로 입력해도 가능


이클립스로 서버 시작시 파일 저장 경로

:\java\work\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\study\pds\saveFile


bat파일로 서버 시작시 파일 저장 경로

D:\java\apache-tomcat-7.0.92\webapps\study\pds\saveFile

파일명이 한글으로 오류날 때 

파일 업로드시 한글로 된 이름의 파일이 오류가 발생하는 경우가 있음. 
server.xml 파일에 URIEncoding="UTF-8" 가 입력되었는지 확인하면 됨.