/**
 * 파일다운로드
 * @param request 
 * @return
 * @throws Exception
 */
@RequestMapping(value = "download.do")
public void downloadFileController(HttpServletRequest req, HttpServletResponse res) throws Exception {
	String mode = req.getParameter("mode");
	String file = req.getParameter("file");
	file = file.replaceAll("\\.\\.\\/", "");  // 부정접근 방지
	String name = req.getParameter("name");
	name = URLEncoder.encode(name, "UTF-8");  //한글깨짐 방지
	String folder = "temp";
	if("stamp".equals(mode)){
		folder = "stamp";
	}else if("course".equals(mode)){
		folder = "course";
	}else if("test".equals(mode)){
		folder = "test";
	}  // 폴더 접근 유효성 체크
	String fileFullPath = ROOT_UPLOAD_DIR+File.separator+folder+File.separator+file;  // 서버에 맞는 업로드 기본 폴더
	File downFile = new File(fileFullPath);  //파일 객체 생성
	if(downFile.isFile()){  // 파일이 존재하면
		int fSize = (int)downFile.length();
		res.setBufferSize(fSize);
		res.setContentType("application/octet-stream");
		res.setHeader("Content-Disposition", "attachment; filename="+name+";");
		res.setContentLength(fSize);  // 헤더정보 입력
		FileInputStream in  = new FileInputStream(downFile);
		ServletOutputStream out = res.getOutputStream();
		try
		{
			byte[] buf=new byte[8192];  // 8Kbyte 로 쪼개서 보낸다.
			int bytesread = 0, bytesBuffered = 0;
			while( (bytesread = in.read( buf )) > -1 ) {
				out.write( buf, 0, bytesread );
				bytesBuffered += bytesread;
				if (bytesBuffered > 1024 * 1024) { //아웃풋스트림이 1MB 가 넘어가면 flush 해준다.
					bytesBuffered = 0;
					out.flush();
				}
			}
		}
		finally {
			if (out != null) {
				out.flush();
				out.close();
			}
			if (in != null) {
				in.close();
			}
			//에러가 나더라도 아웃풋 flush와 close를 실행한다.
		}
	}
}

자바에서 파일을 클라이언트로 내려줄때 heap메모리나 out of memory가 날때가 있다.
서버 메모리가 작아서 문제일 수도 있지만
자바 소스에서 사용한 메모리를 회수하지 못해서 생기는 문제일때도 많다.

기본 반향은 파일을 일정 크기로 쪼개서 내보내고
버퍼에 담긴것은 날려줘야 한다.


+ Recent posts