스프링 프로젝트에서 파일 업로드와 다운로드를 하는 방법을 알아보겠습니다.
이번 포스팅에선 다운로드 예제를 작성했습니다.
추가 메이븐 다운로드 없이 스프링 설정만 하시면 됩니다.
파일 다운로드
web.xml
<!-- Filter -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Filter -->
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
먼저 web.xml에서 필터 설정과 DispatcherServlet상태를 확인하겠습니다.
필터를 통해 utf-8 인코딩 처리를 하였고 servlet-context.xml의 위치는 /WEB-INF/spring/servlet-context.xml 로 지정하였습니다.
servel-context.xml
<!-- spring-donwload bean -->
<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<beans:property name="order" value="0" />
</beans:bean>
<beans:bean id="downloadView" class="com.psw.myapp.utils.DownloadView" />
<!-- /spring-donwload bean -->
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
<beans:property name="order" value="1" />
</beans:bean>
InternalResourceViewResolver의 order순서를 1로 변경하였습니다.
DonwloadView 자바파일에서 다운로드 처리를 진행할 것이며 bean등록 처리를 해기 위해 BeanNameViewResolver를 사용했습니다.
CommonController.java
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/common")
public class CommonController{
private static final String FILE_SERVER_PATH = "C:/test";
@RequestMapping("/download")
public ModelAndView download(@RequestParam HashMap<Object, Object> params, ModelAndView mv) {
String fileName = (String) params.get("fileName");
String fullPath = FILE_SERVER_PATH + "/" + fileName;
File file = new File(fullPath);
mv.setViewName("downloadView");
mv.addObject("downloadFile", file);
return mv;
}
}
모든 파일은 C:/test에 있다고 가정하였습니다.
파일은 전달받은 fileName 파라미터값을 통해 파일을 세팅합니다.
downloadFile에 다운로드할 파일을 처리하고 bean등록을한 downloadView로 넘길것입니다.
DownloadView.java
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
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 {
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
File file = (File)model.get("downloadFile");
if(file != null) {
String fileName = null;
String userAgent = request.getHeader("User-Agent");
if(userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("Trident") > -1){
fileName = URLEncoder.encode(file.getName(), "utf-8").replaceAll("\\+", "%20");;
}else if(userAgent.indexOf("Chrome") > -1) {
StringBuffer sb = new StringBuffer();
for(int i=0; i<file.getName().length(); i++) {
char c = file.getName().charAt(i);
if(c > '~') {
sb.append(URLEncoder.encode(""+c, "UTF-8"));
}else {
sb.append(c);
}
}
fileName = sb.toString();
}else {
fileName = new String(file.getName().getBytes("utf-8"));
}
response.setContentType(getContentType());
response.setContentLength((int)file.length());
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 e){
e.printStackTrace();
}
}
if(out != null) {
out.flush();
}
}
}
}
}
donwloadView는 AbstractView를 상속받아 사용합니다.
AbstractView는 View구현을 위한 추상클래스로 컨트롤러가 반환한 모델과 병합되는 뷰입니다.
앞서 CommonController.java에서 세팅한 file인 downloadFile을 받아서 ie인지 체크 후 헤더 세팅과 OutputStream을 통해 파일을 출력합니다.
또한, 주의사항으로 브라우저마다의 인코딩이 달라서 User-Agent를 통해 접속한 브라우저를 체크하고 출력해줄 파일명을 만들때 인코딩 방식을 다르게 해야합니다. IE의 경우엔 11버전부턴 식별문자가 Trident로 변경되어 MSIE와 같이 조건문에 추가하였습니다.
이제 다운로드가 정상적으로 되는지 테스트 해보겠습니다.
전 board.jsp라는곳에서 처리할 예정이므로 컨트롤러와 jsp를 추가로 만들겠습니다.
BoardController.java
import java.util.HashMap;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/board")
public class BoardController {
@RequestMapping("/board.do")
public ModelAndView board(@RequestParam HashMap<Object, Object> params, ModelAndView mv) {
mv.setViewName("board/board");
return mv;
}
}
board/board.do url로 요청이 들어오면 board/board.jsp를 호출하도록 컨트롤러 설정을 했습니다.
board.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>파일 다운로드</title>
</head>
<body>
<div class="content">
<br/><br/>
<h3>파일 다운로드</h3>
<a href="/common/download.do?fileName=이미지예제.jpg">download</a>
</div>
</body>
</html>
이제 마지막으로 WEB-INF/views/board 디렉토리와 board.jsp파일을 만들고 board.jsp를 작성했습니다.
a태그를 클릭하시면 CommonContorller에 요청을 했다가 DownloadView를 통해 다운로드가 되는 것을 볼 수 있습니다.
IE 인코딩 에러
예제를 그대로 진행하면 한글명때문에 익스에서 하시는분들은 에러가 발생할 수 있습니다.
IE 예외처리 인코딩을 위해 jsp부분을 수정해주시면 됩니다.
board.jsp
<%@page import="java.net.URLEncoder"%>
...
<a href="/common/download.do?fileName=<%=URLEncoder.encode("이미지예제.jpg")%>">download</a>
URLEncoder를 추가 import해주시고 파라미터부분을 인코딩하여 넘기시면 IE에서도 되는 걸 확인 할 수 있습니다.
파일 업로드는 아래 URL에서 진행됩니다.
https://myhappyman.tistory.com/89
'WEB > Spring' 카테고리의 다른 글
SpringBoot - 스프링부트에서 채팅프로그램(소켓통신) 만들기-1(단순 채팅, 메시지 보내기) (63) | 2020.03.05 |
---|---|
Spring - 파일 업로드 예제 (0) | 2020.02.19 |
Spring - tiles 적용 에러 발생 'org.springframework.web.servlet.view.tiles3.TilesConfigurer' not found (2) | 2020.02.13 |
Spring - 타일즈(Tiles) 적용하기 (0) | 2020.02.13 |
Spring - mysql SSH Tunneling(mysql 터널링 접근하기) (0) | 2020.02.03 |