스프링에서 지원하는 다운로드를 쓰려면 아래와 같이 하시오.!
일단 기본적으로 파일 다운로드 처리하기에 앞서서 알아야 할 사항을 배워보도록 하자.
1. 파일링크를 클릭할때 컨트롤러 클래스에게 파일패스와 파일이름을 던져주고
2. 받은 컨트롤러 클래스에서 그 파일 패스와 파일이름으로 file 을 만들어서 (DownloadController)
3. 뷰로 전달을 할 것이다.
4. 그럼 뷰에서 받은 file 정보를 이용해서 실제 파일을 읽어들인 다음 원하는 위치에 쓰는 작업을 한다. (DownloadView)
일반적인 컨트롤러 클래스에서 작업을 한 후, 뷰 페이지로 결과값을 뿌려주는 것인데
일반적인 뷰페이지는 JSP 페이지였다.
하지만 다운로드에 사용될 뷰는 JSP 가 아니라 클래스 파일이다.
그렇기 때문에 아래처럼 일반적으로 사용하던 viewResolver 가 처리하는 것이 아니라
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> <property name="order" value="1"/> </bean>
download 만을 처리하는 viewResolver 가 따로 존재해야 한다. 여기에는 id값이 없다…주의할것!!!!!!!!!
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="0"/> </bean>
주의할 점은 위 두 코드에 포함된 프로퍼티를 보면 order 라는 프로퍼티가 있는데
이 프로퍼티는 두개이상 존재하는 viewResolver 를 위해서
우선순위를 매기는 것이다. 만약 우선순위를 명시 하지 않으면 “가장 낮은 우선순위를 갖게 된다.”
우선순위는 “0”이 가장 먼저 실행되고, 이후로 매겨지는 순서에 따라 실행된다.
다음 viewResolver가 실행되는 기준은 “null” 이 반환되느냐 가 기준이다.
그렇기 때문에 널값이 있을수 없는 InternalResourceViewResolver 가 우선순위가 높게 되면,
다른 viewResolver 는 사용되지 않게되는
문제가 있다. (항상 뷰 이름에 매핑이 되는 뷰 객체를 리턴하기 때문)
그래서 InternalResourceViewResolver 은 우선순위가 가장 낮아야 한다.
그러면 이제 BeanNameViewResolver 를 사용하는 법을 알아 보자
BeanNameViewResolver (파일 다운로드 viewResolver)
“null” 이 반환되지 않는다면, (즉 컨트롤러 클래스에서 리턴되온 뷰페이지 값과 일치하는 빈이 있는 경우)
컨트롤러 클래스에서 리턴되온 뷰페이지 값과 일치하는 빈이 등록되있는 경우는 그 빈에 해당하는 컨트롤러 클래스가
파일 다운로드를 처리하게 된다.
그렇기 때문에 컨트롤러 클래스에서 viewResolver 로 던져줄 뷰페이지 이름과, 처리할 View 클래스 빈이름이 같아야 한다.
(이말을 반대로 하자면, 실제 jsp 가 보여져야될 때는 리턴값과, view 빈 이름이 같아서는 절대 안된다.)
<bean id=”download”/>
– 이 코드가 다운로드를 처리할 뷰 클래스를 등록하는 것이다.
저기 id=”download” 라고 되있는 부분과, 클래스에서 리턴된 값이 같아야 한다.
그리고 url 을 처리할 컨트롤러 클래스도 등록되야되겠지.
<bean id="down" class="Spring.DownloadController"/>
여기 까지가 좀 복잡하지만 servlet.xml 파일을 설정하는 부분이다.
하나하나 천천히 다시 읽어보면 이해가 될 것이다.
파일 이름에 링크를 걸어서 컨트롤러 클래스로 넘기는 부분부터 시작
<a href="/Spring_margo/download.do?path=${path }&fileName=${itemBean.fileName }" > ${itemBean.fileName } </a> download.do 로 파일네임과 패스를 넘기게 되어있다.
그럼 저 url 을 처리하는 컨트롤 클래스는 아래와 같다.
<bean id="down" class="Spring.DownloadController"/> }
@Controller public class DownloadController implements ApplicationContextAware{ private WebApplicationContext context = null; @RequestMapping("download.do") public ModelAndView download(@RequestParam("path")String path, @RequestParam("fileName")String fileName){ String fullPath = path + "\\" + fileName; File file = new File(fullPath); return new ModelAndView("download", "downloadFile", file); } @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { // TODO Auto-generated method stub this.context = (WebApplicationContext)arg0; } }
@RequestMapping(“download.do”) 어노테이션으로 지정해준것처럼
download.do 가 들어오면 저 메소드가 동작한다.
링크에서 준것처럼 패스와 파일네임을 받아서
파일에 조합해서 쓰고 “download” 뷰페이지로 파일을 “downloadFile”이름으로 삽입하고 리턴시킨다.
그러면 <bean#e31600″>BeanNameViewResolver“>
저 viewResolver 가 먼저 리턴을 처리하려 할 것이다.
“download”로 등록된 빈이 있는지 찾아 보는데 우리는 아까 “download”로 뷰클래스를 등록시켜 놓았다.
<bean id="down" class="Spring.DownloadController"/> }
이제 DownloadView.java 클래스가 뷰페이지로 동작할 것이다.
뷰페이지에서는 map 에 등록된 파일을 이용해서 encoding 설정과 헤더설정을 해준 후 파일을 지정위치에 쓴다.
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 { public void Download(){ setContentType("application/download; utf-8"); } @Override protected void renderMergedOutputModel(Map<string, object=""> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub File file = (File)model.get("downloadFile"); System.out.println("DownloadView --> file.getPath() : " + file.getPath()); System.out.println("DownloadView --> file.getName() : " + file.getName()); 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")); }// end if; 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){} } }// try end; out.flush(); }// render() end; } </string,>