구리

TIL_210624_Spring 파일 업로드 처리 본문

SPRING FRAMEWORK

TIL_210624_Spring 파일 업로드 처리

guriguriguri 2021. 6. 23. 11:33

목차

 

파일 업로드 처리

(1) 파일 업로드 입력 화면

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta charset="UTF-8">
	<title>새글등록</title>
</head>

<body>
	<center>
		<h1>글 등록</h1>
		<a href="logout.do">Log-out</a>
		<hr />

		<form action="insertBoard.do" method="post" enctype="multipart/form-data">
			<table border="1" cellpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input type="text" name="title" /></td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">작성자</td>
					<td align="left"><input type="text" name="writer" size="10" /></td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">내용</td>
					<td align="left"><textarea name="content" cols="40" rows="10"></textarea></td>
				</tr>
				
				<tr>
					<td bgcolor="orange" width="70">업로드</td>
					<td><input type="file" name="uploadFile" /></td>
				</tr>
				
				<tr>
					<td colspan="2" align="center">
						<input type="submit" value="새글 등록" />
					</td>
				</tr>
				
			</table>
		</form>
		<hr />
		<a href="getBoardList.jsp">글목록</a>
	</center>
</body>
</html>

파일 업로드를 위해 form 태그에 entype 속성 추가 후 멀티파트 형식인 "multipart/form-data"로 지정하며 input type="file" 태그를 추가합니다.

 

(2) Command 객체 수정

업로드할 파일 정보 추가로 인해 BoardVO에 파일 관련 변수를 추가합니다.

package com.springbook.biz.board;

import java.sql.Date;

import org.springframework.web.multipart.MultipartFile;

// VO
public class BoardVO {
	private int seq;
	private String title;
	private String writer;
	private String content;
	private Date regDate;
	private int cnt;
	private String searchCondition;
	private String searchKeyword;
	private MultipartFile uploadFile;
	
	public BoardVO() {}
	
	public int getSeq() {
		return seq;
	}
	public void setSeq(int seq) {
		this.seq = seq;
	}
	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 Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	
	public String getSearchCondition() {
		return searchCondition;
	}

	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}

	public String getSearchKeyword() {
		return searchKeyword;
	}

	public void setSearchKeyword(String searchKeyword) {
		this.searchKeyword = searchKeyword;
	}

	public MultipartFile getUploadFile() {
		return uploadFile;
	}

	public void setUploadFile(MultipartFile uploadFile) {
		this.uploadFile = uploadFile;
	}

	@Override
	public String toString(){
		return "BoardVO [seq=" + seq + ", title=" + title + ", writer=" + writer + ",content= " + content + ", regDate = " + regDate + ", cnt = " + cnt +"]";
		
	}
}

 

(3) FileUpload 라이브러리 추가

- pom.xml에 FileUpload 라이브러리 내려받기 위한 <dependency> 엘리먼트 추가

<!-- FileUpload -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>

 

(4) MultipartReslover 설정

<!-- 파일 업로드 설정 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="maxUploadSize" value="100000"></property>
	</bean>

 - id=multipartResolver : CommonsMultipartResolver 클래스는 이름이 정해져 있어 DispatcherServlet은 특정 이름으로

                                                등록된CommonsMultipartResolver 객체만 인식하도록 되어 있습니다. 따라서 id 값은 변경불가합니다.

 - maxUploadSize : 파일 크기 제한 설정

 

스프링 컨테이너가 "/insertBoard.do" 요청에 대해 insertBoard() 메소드 호출후 BoardVo 객체도 생성하여 전달합니다.

이때  "multipartResolver"라는 이름의 CommonsMultipartResolver 객체가 존재해야만 스프링 컨테이너는 MultipartFile 객체를 생성할 수 있습니다.

 

MultipartFile 인터페이스 제공 메소드 설명
String getOriginalFilename() 업로드한 파일명을 문자열로 리턴
void transferTo(File destFile) 업로드한 파일을 destFile에 저장
boolean isEmpty() 업로드한 파일 존재 여부 리턴(없으면 true)

 

(5) 파일 업로드 처리

package com.springbook.view.board;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.multipart.MultipartFile;

import com.springbook.biz.board.BoardService;
import com.springbook.biz.board.BoardVO;

@Controller
@SessionAttributes("board")
public class BoardController {
	@Autowired
	private BoardService boardService;
	
	@RequestMapping("/insertBoard.do")
	public String insertBoard(BoardVO vo) throws IOException{
		// 파일 업로드 처리
		MultipartFile uploadFile = vo.getUploadFile();
		if(!uploadFile.isEmpty()){
			String fileName = uploadFile.getOriginalFilename();
			uploadFile.transferTo(new File("C:/" + fileName));
		}
		boardService.insertBoard(vo);
		return "getBoardList.do";
	}
}

 

예외 처리

1. 어노테이션 기반 예외 처리

presentation-layer.xml에 mvc 네임스페이스 추가 후 <mvc:annotation-driven> 엘리먼트 설정

(설정해야만 @ExceptionHandler 어노테이션 인식 가능)

	<!-- 예외처리 관련 어노테이션 설정 -->
	<mvc:annotation-driven></mvc:annotation-driven>

 

예외 화면이 서비스되도록 예외처리 클래스 작성

package com.springbook.view.common;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice("com.springbook.view")
public class CommonExceptionHandler {
	@ExceptionHandler(ArithmeticException.class)
	public ModelAndView handleArithmeticException(Exception e){
		ModelAndView mav = new ModelAndView();
		mav.addObject("exception", e);
		mav.setViewName("/common/arithmeticError.jsp");
		return mav;
	}
	
	@ExceptionHandler(NullPointerException.class)
	public ModelAndView handleNullPointerException(Exception e){
		ModelAndView mav = new ModelAndView();
		mav.addObject("exception", e);
		mav.setViewName("/common/nullPointercError.jsp");
		return mav;
	}
	
	@ExceptionHandler(Exception.class)
	public ModelAndView handleException(Exception e){
		ModelAndView mav = new ModelAndView();
		mav.addObject("exception", e);
		mav.setViewName("/common/error.jsp");
		return mav;
	}
}

@@ControllerAdvice 어노테이션으로 인해 CommonExceptionHandler 객체가 자동으로 생성되고 설정한 패키지로 시작하는 컨트롤러에서 예외가 발생하는 순간 @ExceptionHandler 어노테이션으로 인해 지정한 메소드가 실행됩니다.

 

기본 예외 화면 생성 후 해당 폴더에 위에서 명시한 이름으로 총 3개의 예외 페이지 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page isErrorPage="true" %>
<!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 bgcolor="#ffffff" text="#000000">
	<!-- 타이틀 시작 -->
	<table width="100%" border="1" cellspacing="0" cellpadding="0">
		<tr>
			<td align="center" bgcolor="orange"><b>기본 에러 화면입니다</b></td>
		</tr>
	</table>
	<br>
	
	<!-- 에러 메시지 -->
	<table width="100%" border="1" cellspacing="0" cellpadding="0">
		<tr>
			<td align="center">
			<br /><br /><br /><br />
			Message : ${exception.message}
			<br /><br /><br /><br />
			</td>
		</tr>
	</table>
</body>
</html>

서버 실행 후 로그인 페이지에서 아이디 미입력 후 로그인 처리를 하면 해당 예외 처리 페이지로 이동하게 됩니다.

 

2. XML 기반의 예외 처리

presentation-layer.xml 파일에서 SimpleMappingExceptionResolver 클래스를 <bean> 등록만 하면 예외 처리가 가능합니다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">

	
	<context:component-scan base-package="com.springbook.view"></context:component-scan>
	
	<!-- 파일 업로드 설정 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<property name="maxUploadSize" value="100000"></property>
	</bean>
	
	<!-- 에외 처리 설정 - xml 기반 -->
	<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
			<props>
				<prop key="java.lang.ArithmeticException">
					common/arithmeticError.jsp
				</prop>
				<prop key="java.lang.NullPointerException">
					nullPointerError.jsp
				</prop>
			</props>
		</property>
		<property name="defaultErrorView" value="common/error.jsp"></property>
	</bean>
	<!-- 예외처리 관련 어노테이션 설정
	<mvc:annotation-driven></mvc:annotation-driven>
	 -->
</beans>

ArithmeticException, NullPointerException 발생시 설정한 화면이 전송되며 등록되지 않은 예외 발생시 defaultErrorView로 설정한 error.jsp 화면이 전송됩니다.

 

출처 : 스프링 퀵 스타트