/**
 * 파일다운로드
 * @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가 날때가 있다.
서버 메모리가 작아서 문제일 수도 있지만
자바 소스에서 사용한 메모리를 회수하지 못해서 생기는 문제일때도 많다.

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


자바로 파일다운로를 하는 경우

파일명에 한글이 있거나 공백, 가로등 특수문자가 있는경우

브라우저 별로 참 다양한 파일명으로 다운로드 된다.


각 브라우저별로 파일을 다운로드 할때 적당한 인코딩을 하여

다운로드 받는 파일명 처리를 해주어야 한다.


아래 소스에서 각 브라우저 별로

다운로드 되는 파일명을 적절하게 인코딩하여 내려준다.


@RequestMapping( value = "/download.do" )

public void filedown( @RequestParam Map<String, Object> param, HttpServletRequest request,

HttpServletResponse response ) throws Exception {


File file = (File) param.get( "downloadFile" );

String displayFileName = String.valueOf( param.get( "displayFileName" ) );

String encodedFilename = "";

response.setContentType( "application/download; UTF-8" );

response.setContentLength( (int) file.length() );


String header = request.getHeader( "User-Agent" );

if ( header.indexOf( "MSIE" ) > -1 ) {

encodedFilename = URLEncoder.encode( displayFileName, "UTF-8" ).replaceAll( "\\+", "%20" );

}

else if ( header.indexOf( "Trident" ) > -1 ) { 

encodedFilename = URLEncoder.encode( displayFileName, "UTF-8" ).replaceAll( "\\+", "%20" );

}

else if ( header.indexOf( "Chrome" ) > -1 ) {

StringBuffer sb = new StringBuffer();

for ( int i = 0; i < displayFileName.length(); i++ ) {

char c = displayFileName.charAt( i );

if ( c > '~' ) {

sb.append( URLEncoder.encode( "" + c, "UTF-8" ) );

}

else {

sb.append( c );

}

}

encodedFilename = sb.toString();

}

else if ( header.indexOf( "Opera" ) > -1 ) {

encodedFilename = "\"" + new String( displayFileName.getBytes( "UTF-8" ), "8859_1" ) + "\"";

}

else if ( header.indexOf( "Safari" ) > -1 ) {

encodedFilename = "\"" + new String( displayFileName.getBytes( "UTF-8" ), "8859_1" ) + "\"";

encodedFilename = URLDecoder.decode( encodedFilename );

}else{

encodedFilename = "\"" + new String( displayFileName.getBytes( "UTF-8" ), "8859_1" ) + "\"";

encodedFilename = URLDecoder.decode( encodedFilename );

}

response.setHeader( "Content-Disposition", "attachment; filename=\"" + encodedFilename + "\";" );

response.setHeader( "Content-Transfer-Encoding", "binary" );


OutputStream out = response.getOutputStream();

FileInputStream fis = null;


try {


fis = new FileInputStream( file );

FileCopyUtils.copy( fis, out );

}

catch ( FileNotFoundException e ) {

if ( LOGGER.isErrorEnabled() ) {

LOGGER.error( e.getMessage(), e );

}

throw new KpxBizException( messageSource, "ERROR.0104" );

}

finally {

IOUtils.closeQuietly( fis );

}


out.flush();

}



+ Recent posts