스프링 파일 다운로드를 다뤄볼게요.
그냥 쉽게 쉽게 예제랑 방법만 첨부할게요~
Spring 3.1이고요 저도 검색을 통해서 알아낸거지만 참 스프링은 개발하기 좋게 갖춰진 도구인 것 같아요.
스프링 파일 다운로드를 하기에 앞서
XML 설정을 좀 해볼게요.
<bean id="springDownload" class="util.component.FileDownload"/>
bean을 하나 생성해주는데요. 이 bean은 viewresolver를 통해서 파일 다운로드 처리를 하는 클래스로 넘어가게 됩니다.
보통은 viewResolver에 prefix와 suffix를 제외하고 String문자열로 jsp 파일의 경로를 넣어주잖아요.
하나 궁금한게 생기죠 .. 저건 bean인데 viewResolver에서 어떻게 쟤가 그 놈인지 알아볼 수 있나요 ? 라고
물론 그 설정도 해주어야 합니다.
아래와 같이요.
1. ViewResolver
이건 흔히 ViewResolver를 설정할때 이렇게 쓰죠. 보통 쓰던거랑 똑같습니다.
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/views" p:suffix=".jsp" p:order="1"/>
2.FileDownload Resolver
일단 클래스가 다릅니다. org.springframework.web.servlet.view.BeanNameViewResolver beanNameResolver라고 되어 있네요. Bean이름으로 return할 수가 있겠네요. 다양한 부분에서 응용할 수 있을 것 같습니다.
여기서 보셔야 할거는 property name="order" value="0" 이고요. 이렇게 설정을 해주어야 beanName이 String 타입으로 return 되었을때 이 BeanNameResolver가 받게 됩니다. 그래서 우선순위로 0을 줌으로서 bean에서 먼저 찾고 없으면 InternalResourceViewResolver에서 찾게 됩니다.
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="0"/>
</bean>
XML에 BEAN이랑 BeanNameViewResolver를 설정해서 beanName으로도 viewResolver를 사용할 수 있게 설정을 마쳤네요.
그럼 이걸 어떻게 설정할까요 ?
첫번째로,
<bean id="springDownload" class="util.component.FileDownload"/>
이렇게 bean을 생성한 클래스를 만들어줘야겠죠. 이 클래스는 직접적으로 파일만 읽어와서 스트림으로 떨구는 것만 작업할 겁니다. 그래야 다른 파일다운로드에서도 공통적으로 쓸 수 있으니까요.
public class FileDownload extends AbstractView { public void Download(){
setContentType("application/download; utf-8");
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
File file = (File)model.get("fileDownload");
String type = model.get("type").toString();
response.setContentType(getContentType());
response.setContentLength((int)file.length());
String userAgent = request.getHeader("User-Agent");
boolean ie = userAgent.indexOf("MSIE") > -1;
String fileName = null;
if(ie){
fileName = URLEncoder.encode(file.getName(), "utf-8");
} else {
fileName = new String(file.getName().getBytes("utf-8"));
}
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName+type+"\";");
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){}
}
}
out.flush();
}
}
이 소스는 저도 어디서 긁어왔네요 ㅋㅋ
보시다시피
Map<String, Object> model,
HttpServletRequest request,
HttpServletResponse response
이러한 인자들을 넘겨받네요.
두번째로,
자 그럼 Controller에서는 어떻게 사용할까요.
model.addAttribute("fileDownload", file);
이렇게 File을 생성해서 fileDownload란 key로 ModelMap에 담아서 넘깁니다.
위에 보시는 것처럼 위 클래스에도 ModelMap을 인자로 받고 있기 때문에 넘겨받을 수 있습니다. 찾아보시면 fileDownload 라는 key를 get하는걸 찾을 수 있어요.
return "springDownload";
자 이게 중요하죠. XML에서 생성했던 BeanName을 여기서 씁니다. 그래야 우리가 생성한 Class로 resolve 되게 되니까요.
정리할게요.
1. 파일 다운로드 처리를 담당할 공통 클래스를 만들고 xml에 bean을 생성한다.
2. dispatcher-servlet.xml에 BeanNameResolver를 생성하고 order를 0으로 설정한다
3. Controller에서 return "생성한 빈네임" 으로 해야하며 파일을 다운로드 할 객체를 model.addattribute("")로 넘기거나 파일 path만 넘겨서 파일 객체를 얻어올 수 있어야 한다.
라는 겁니다.
끝이구요~ 화면에서는 당연히 download할때 target을 hidden frame으로 줘야 하는거 잊지마시구요. 다른 방법 있으면 공유 좀 ㅋㅋ 전 아직 이렇게 쓰네요..
'SPRING' 카테고리의 다른 글
[MONGODB+SPRING] 몽고디비+스프링 연계하기 (0) | 2015.07.17 |
---|---|
[Spring MVC] 스프링 MVC 아키텍쳐 (0) | 2014.04.26 |
[토비] Spring 싱글톤 패턴의 이야기 (0) | 2014.04.12 |
[MYBATIS] KEY값을 생성하고 생성된 KEY 되돌려 받기 (0) | 2013.10.24 |
[ERROR] Maven 환경의 프로젝트 구동시 에러 (0) | 2013.10.08 |