- 파일 업로드 : 2013/10/23 - [Web/Spring] - 스프링(Spring) 파일 업로드(File Upload)


1. 스프링(Spring) 파일 다운로드(File Download)

- 다운로드를 위한 View 처리를 JSP 파일이 아닌 클래스로 처리

- 클래스로 뷰 처리를 하기 위해 다운로드 처리하는 viewResolver를 추가 (org.springframework.web.multipart.commons.CommonsMultipartResolver)

- 클래스 뷰로 사용할 클래스를 <bean> 태그로 객체 생성한다.

- 두 개이상의 viewResolver 처리를 위해 <property> 태그의 name 속성의 order 로 우선순위를 부여


2. war 파일 첨부

SpringFile.war


3. 코딩 소스

// FileController.java

package controller.com.tistory.gangzzang;

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

import model.com.tistory.gangzzang.FileDAO;
import model.com.tistory.gangzzang.FileDTO;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class FileController implements ApplicationContextAware {
	
	private WebApplicationContext context = null;

	@RequestMapping(value = "/fileDown.do", method = RequestMethod.GET)
	public ModelAndView fileDown(@RequestParam("fileName") String fileName) {
		String fullPath = "C:/images/" + fileName ;
		File downloadFile = new File(fullPath);
		return new ModelAndView("download", "downloadFile", downloadFile);
	}
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.context  = (WebApplicationContext) applicationContext;
	}
	
	@RequestMapping(value = "/list.do", method = RequestMethod.GET)
	public ModelAndView fileList() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("fileList");
		
		ArrayList list =  FileDAO.getInstance().listFile();
		mv.addObject("list", list);
		return mv;
	}
	
	@RequestMapping(value = "/file.do", method = RequestMethod.GET)
	public ModelAndView fileForm() {
		ModelAndView mv = new ModelAndView();
		mv.setViewName("fileForm");
		return mv;
	}
	
	@RequestMapping(value = "/file.do", method = RequestMethod.POST)
	public String fileSubmit(FileDTO dto) {
		MultipartFile uploadfile = dto.getUploadfile();
		if (uploadfile != null) {
			String fileName = uploadfile.getOriginalFilename();
			long fileSize = uploadfile.getSize();
			dto.setFileName(fileName);
			dto.setFileSize(fileSize);
		
			try {
				// 1. FileOutputStream 사용
				// byte[] fileData = file.getBytes();
				// FileOutputStream output = new FileOutputStream("C:/images/" + fileName);
				// output.write(fileData);
				
				// 2. File 사용
				File file = new File("C:/images/" + fileName);
				uploadfile.transferTo(file);
			} catch (IOException e) {
				e.printStackTrace();
			} // try - catch
		} // if
		
		int re = FileDAO.getInstance().insertFile(dto);
		if (re == 0)
			return "실패"; // 실패했을 때 페이지 구현은 패스
		else
			return "redirect:list.do";
	}
}
// FileDAO.java

package model.com.tistory.gangzzang;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class FileDAO {
	
	private static FileDAO instance = new FileDAO();
	
	public static FileDAO getInstance() {
		return instance;
	}
	
	private FileDAO() {}
	
	public int insertFile(FileDTO dto) {
		int re = 0;
		Connection con = null;
		PreparedStatement ps = null;
		String sql = "INSERT INTO fileboard(name,pwd,title,content,filename,filesize) VALUES(?,?,?,?,?,?)";
		try {
			con = UtillDB.getCon(con);
			ps = con.prepareStatement(sql);
			ps.setString(1, dto.getName());
			ps.setString(2, dto.getPwd());
			ps.setString(3, dto.getTitle());
			ps.setString(4, dto.getContent());
			ps.setString(5, dto.getFileName());
			ps.setLong(6, dto.getFileSize());
			re = ps.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			UtillDB.closeDB(con, ps);
		} // try - catch - finally
		return re;
	} // insertFile()
	
	public ArrayList listFile() {
		ArrayList list = new ArrayList();
		Connection con = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		String sql = "SELECT name,title,content,filename,filesize FROM fileboard";
		try {
			con = UtillDB.getCon(con);
			ps = con.prepareStatement(sql);
			rs = ps.executeQuery();
			while (rs.next()) {
				FileDTO dto = new FileDTO();
				dto.setName(rs.getString("name"));
				dto.setTitle(rs.getString("title"));
				dto.setContent(rs.getString("content"));
				dto.setFileName(rs.getString("filename"));
				dto.setFileSize(rs.getLong("filesize"));
				list.add(dto);
			} // while
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			UtillDB.closeDB(con, ps, rs);
		} // try - catch - finally
		return list;
	} // listFile()
	
}
// FileDTO.java

package model.com.tistory.gangzzang;

import org.springframework.web.multipart.MultipartFile;

public class FileDTO {
	private String name, pwd, title, content, fileName;
	private long fileSize;
	private MultipartFile uploadfile;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public String getTitle() {
		return title;
	}

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

	public String getContent() {
		return content;
	}

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

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public long getFileSize() {
		return fileSize;
	}

	public void setFileSize(long fileSize) {
		this.fileSize = fileSize;
	}

	public MultipartFile getUploadfile() {
		return uploadfile;
	}

	public void setUploadfile(MultipartFile uploadfile) {
		this.uploadfile = uploadfile;
	}

}
// UtillDB.java

package model.com.tistory.gangzzang;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UtillDB {
	
	public static Connection getCon(Connection con) {
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			con = DriverManager.getConnection("jdbc:oracle:thin:@203.236.209.185:1521:XE", "gz", "tiger");
		} catch (SQLException e) {
			System.out.println("SQLException : " + e.getMessage());
		} catch (Exception e) {
			System.out.println("Exception : " + e.getMessage());
		} // try - catch
		return con;
	} // getCon() : Connection 객체를 DBCP 연결 후에 리턴
	
	public static void closeDB(Connection con, PreparedStatement ps, ResultSet rs) {
		if (rs != null) { try { rs.close(); } catch (Exception e) { } }
		if (ps != null) { try { ps.close(); } catch (Exception e) { } }
		if (con != null) { try { con.close(); } catch (Exception e) { } }
	} // closeDB() : SELECT DB 연결 종료
	
	public static void closeDB(Connection con, PreparedStatement ps) {
		if (ps != null) { try { ps.close(); } catch (Exception e) { } }
		if (con != null) { try { con.close(); } catch (Exception e) { } }
	} // closeDB() : SELECT 외 DB 연결 종료
	
} // UtillDB
// DownloadView.java

package view.com.tistory.gangzzang;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.FileCopyUtils;
import org.springframework.web.servlet.view.AbstractView;

public class DownloadView extends AbstractView {

	public DownloadView() {
		setContentType("applicaiton/download;charset=utf-8");
	}

	@Override
	protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		File file = (File) model.get("downloadFile");
		
		response.setContentType(getContentType());
		response.setContentLength((int)file.length());
		
		String fileName = java.net.URLEncoder.encode(file.getName(), "UTF-8");
		
		response.setHeader("Content-Disposition", "attachment;filename=\""+fileName+"\";");
		response.setHeader("Content-Transfer-Encoding", "binary");
		
		OutputStream out = response.getOutputStream();
		FileInputStream fis = null;
		
		try {
			fis = new FileInputStream(file);
			FileCopyUtils.copy(fis, out);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fis != null) { try { fis.close(); } catch (Exception e2) {}}
		}
		out.flush();
	}
}






	
	
	
		
		
		
	
	
	
		
	
	
	
	
	






  SpringBoard
  
  
  	encodingFilter
  	org.springframework.web.filter.CharacterEncodingFilter
  	
  		encoding
  		UTF-8
  	
  
  
  
  	encodingFilter
  	/*
  
  
  
  	dispatcher
  	org.springframework.web.servlet.DispatcherServlet
  	
  		contextConfigLocation
  			/WEB-INF/beans.xml
  	
  
  
  
  	dispatcher
  	*.do
  
  

<!-- fileForm.jsp -->

<%@ 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>
</head>
<body>
	<form action="file.do" method="post" enctype="multipart/form-data">
		<fieldset>
			<table>
				<tr>
					<th>이름</th>
					<td><input type="text" name="name" required="required" placeholder="이름"></td>
				</tr>
				<tr>
					<th>비밀번호</th>
					<td><input type="password" name="pwd" required="required" placeholder="비밀번호"></td>
				</tr>
				<tr>
					<th>파일</th>
					<td><input type="file" name="uploadfile" required="required"></td>
				</tr>
				<tr>
					<th>제목</th>
					<td><input type="text" name="title" required="required" placeholder="제목"></td>
				</tr>
				<tr>
					<th>내용</th>
					<td><textarea rows="20" cols="40" name="content" required="required" placeholder="내용"></textarea></td>
				</tr>
				<tr>
					<td colspan="2">
						<input type="submit" value="작성">
						<input type="reset" value="취소">
					</td>
				</tr>
			</table>
		</fieldset>
	</form>
</body>
</html>


<!-- fileList.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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
th {
	color: #FFFFFF;
	
	background: #a90329; /* Old browsers */
	/* IE9 SVG, needs conditional override of 'filter' to 'none' */
	background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2E5MDMyOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjQ0JSIgc3RvcC1jb2xvcj0iIzhmMDIyMiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM2ZDAwMTkiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
	background: -moz-linear-gradient(top,  #a90329 0%, #8f0222 44%, #6d0019 100%); /* FF3.6+ */
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a90329), color-stop(44%,#8f0222), color-stop(100%,#6d0019)); /* Chrome,Safari4+ */
	background: -webkit-linear-gradient(top,  #a90329 0%,#8f0222 44%,#6d0019 100%); /* Chrome10+,Safari5.1+ */
	background: -o-linear-gradient(top,  #a90329 0%,#8f0222 44%,#6d0019 100%); /* Opera 11.10+ */
	background: -ms-linear-gradient(top,  #a90329 0%,#8f0222 44%,#6d0019 100%); /* IE10+ */
	background: linear-gradient(to bottom,  #a90329 0%,#8f0222 44%,#6d0019 100%); /* W3C */
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a90329', endColorstr='#6d0019',GradientType=0 ); /* IE6-8 */
}

td {
	text-align: center;
	font-size: 9pt;
}
</style>
</head>
<body>
	<fieldset>
	<table style="border: 1px; width: 1400px;">
		<tr>
			<th style="width: 300px">이름</th>
			<th style="width: 200px">제목</th>
			<th style="width: 400px">내용</th>
			<th style="width: 400px">파일명</th>
			<th style="width: 100px">파일사이즈</th>
		</tr>
		
		<c:if test="${ !empty list }">
			<c:forEach items="${ list }" var="list">
				<tr>
					<td width="300px">${ list.name }</td>
					<td width="200px">${ list.title }</td>
					<td width="400px">${ list.content }</td>
					<td width="400px"><a href="fileDown.do?fileName=${ list.fileName }">${ list.fileName }</a></td>
					<td width="100px">${ list.fileSize }</td>
				</tr>
			</c:forEach>
		</c:if>
		
		<c:if test="${ empty list }">
			<tr>
				<td colspan="5">등록된 게시물이 없습니다.</td>
			</tr>
		</c:if>
	</table>
	</fieldset>
</body>
</html>


4. 실행 화면



+ Recent posts