티스토리 뷰


파일 업로드에 이어 파일 다운로드를 배워 보겠습니다.

1. content.jsp ( 게시판의 글을 읽는 View 페이지 에서 다운로드할 파일을 클릭한다. )

2. download.ktds 요청과 함께 파일 이름이 파라미터로 넘어간다

3. 파일 이름을 가지고서 실제 파일이 저장되어 있는 경로에 파일을 가져와 전송한다.


◎ content.jsp 파일에서 다운로드 요청을 날리는 라인입니다.

<a href="/bbs2/download.ktds?fname=${article.fname}">${article.fname}</a>

◎ controller 에서 요청을 받아 처리할 소스를 작성합니다.

	@RequestMapping("/download.ktds")
	public ModelAndView download(@RequestParam("fname") String fname) {
		String realFolder = "d:/upload/";
		mav = new ModelAndView();

		mav.addObject("fileName", new File(realFolder + fname));
		mav.setViewName("downloadView");
		return mav;
	}

파일 이름과 본인이 지정한 업로드 폴더를 이용하여, File 객체에 담고 ModelAndView의 객체로 저장합니다.

ModelAndView의 View 이름을 downloadView 로 지정합니다

여기서 downloadView 는 View 이름을 가지고서, Download 를 처리 할 Bean 을 연결 하기 위해서 입니다.

앞서서 JSON 처리할 때 살펴본 BeanNameViewResolver 가 여기서 또 활용 됩니다.

bbs의 bean 설정 파일에 BeanNameViewResolver 를 추가하고, download를 처리할 bean 인 DownloadImpl.java 도 등록을 합니다

<bean id="downloadView" class="com.ktds.bbs.service.DownLoadImple"></bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" />

여기서 중요한 점은 bean id downloadView 와 ModelAndView의 downloadView 이름이 같아야 BeanNameViewResolver가 bean 연결을 해줍니다.

◎ DownloadImpl.java의 소스 코드 입니다.

package com.ktds.bbs.service;

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.web.servlet.view.AbstractView;

public class DownLoadImple extends AbstractView {
	@Override
	protected void renderMergedOutputModel(Map<String, Object> map, HttpServletRequest req, HttpServletResponse res) throws Exception {

		String fileName = null;
		File file = (File) map.get("fileName");

		res.setContentType("application/download;");
		int length = (int) file.length();
		res.setContentLength(length);

		// 익스플로러 인지 확인
		String userAgent = req.getHeader("User-Agent");
		boolean ie = userAgent.indexOf("MSIE") > -1;

		if (ie) {
			fileName = URLEncoder.encode(file.getName(), "utf-8").replace("+",	"%20");
		} else {
			fileName = new String(file.getName().getBytes("utf-8"), "iso-8859-1").replace("+", "%20");
		}

		res.setHeader("Content-Disposition", "attachment;" + " filename=\""	+ fileName + "\";"); 
		OutputStream out = res.getOutputStream();
		FileInputStream fis = null;

		try {
			int temp;
			fis = new FileInputStream(file);
			while ((temp = fis.read()) != -1) {
				out.write(temp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

AbstractView 로 상속을 하면, View 로 활용할 수 있다.

AbstractView를 상속하면, 추상메소드인 renderMergedOutputModel 를 구현하여 하는데 자세한 내용은 API를 더 참고해보도록 한다.

이 메소드의 인수는 ( map<string, object>, HttpServletRequest req, HttpServletResponse res ) 3가지 이며,

첫 번째 map 은 앞에서 모델에 입력한 file 정보가 될 것이다. 이 map 과 request, response를 이용하여 위 소스 코드와 같이 다운로드가 가능해지도록 구현하면 다운로드가 가능해진다.

또한, 브라우저 별로 url encoding 이 조금씩 다르므로 위의 explorer 와 그 외의 브라우저로 구분하는 것 처럼

fileName 을 변환 시켜야 한다. (이 내용은 검색해서 더 공부 해보도록 한다)

댓글