Programing/JAVA

자바 파일 다운로드 소스, 한글인코딩, 브라우져 문제 해결

리커니 2017. 11. 20.
반응형

 

자바 파일 다운로드 소스, 한글인코딩, 브라우져 문제 해결

 

 

[ jsp ] filename 을 get 방식으로 보낸다.

$(document).ready(function(){
    $('#fileDown').click(function(){

        var filename = $('#fileName').val();
        window.location.assign('${ctx}/infoCenter/download.do?fileName='+fileName);
    });
});

 

[ Java Controller ] 파일 경로 설정 (프로젝트 내에 있는 파일)

- 서버 로컬에 있는 파일이라면 절대경로를 입력.

 @RequestMapping(value="/download.do", produces="text/plain;charset=UTF-8")
 public void fileDownload(HttpServletRequest request, HttpServletResponse response){
     String fileName = request.getParameter("fileName");
     String path = request.getSession().getServletContext().getRealPath("/");
  
     File file = null;
     InputStream is = null;
     OutputStream os = null;
  
     String mimetype = "application/x-msdownload";
     response.setContentType(mimetype);
  
     try {
         setDisposition(fileName, request, response);
   
         file = new File(path+"\\resource\\download\\"+fileName);
         is = new FileInputStream(file);
         os = response.getOutputStream();
   
         byte b[] = new byte[(int) file.length()];
         int leng = 0;
   
         while((leng = is.read(b)) > 0){
             os.write(b,0,leng);
         }
   
         is.close();
         os.close();
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

 

[ Java Controller ] setDisposition - 브라우져에 따른 공백 처리, 인코딩(UTF-8)

void setDisposition(String filename, HttpServletRequest request,
HttpServletResponse response) throws Exception {
    String browser = getBrowser(request);
    String dispositionPrefix = "attachment; filename=";
    String encodedFilename = null;

    if (browser.equals("MSIE")) {
        encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll(
        "\\+", "%20");
    } else if (browser.equals("Firefox")) {
        encodedFilename = "\""
        + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
    } else if (browser.equals("Opera")) {
        encodedFilename = "\""
        + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
    } else if (browser.equals("Chrome")) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < filename.length(); i++) {
        char c = filename.charAt(i);
        if (c > '~') {
            sb.append(URLEncoder.encode("" + c, "UTF-8"));
        } else {
            sb.append(c);
        }
    }
    encodedFilename = sb.toString();
    } else {
        throw new IOException("Not supported browser");
    }

    response.setHeader("Content-Disposition", dispositionPrefix
    + encodedFilename);

    if ("Opera".equals(browser)) {
        response.setContentType("application/octet-stream;charset=UTF-8");
    }

}

 

[ Java Controller ] getBrowser - 브라우져 구분 

private String getBrowser(HttpServletRequest request) {
      String header = request.getHeader("User-Agent");
      if (header.indexOf("MSIE") > -1) {
           return "MSIE";
      } else if (header.indexOf("Chrome") > -1) {
           return "Chrome";
      } else if (header.indexOf("Opera") > -1) {
           return "Opera";
      } else if (header.indexOf("Firefox") > -1) {
           return "Firefox";
      } else if (header.indexOf("Mozilla") > -1) {
           if (header.indexOf("Firefox") > -1) {
                return "Firefox";
           }else{
                return "MSIE";
           }
      }
      return "MSIE";
 }

 

[추가 - 대용량 처리 문제 해결]

 

 

java.controlloer 에서 아래와 같이 바이트 크기를 정할 경우

파일이 크기가 클 경우 팅기는 현상이 발생합니다.

'웹페이지가 일시적으로 다운되었거나 새 웹 주소로 완전히 이동했을 수 있습니다.' 에러 발생

byte b[] = new byte[(int) file.length()]; //용량이 커질경우 바이트 버퍼가 커짐
int leng = 0;
   
while((leng = is.read(b)) > 0){  //한번에 처리를 하면 문제 발생
    os.write(b,0,leng);
}

 

그래서 아래와 같이 버퍼를 나누어 받아주어야 합니다.

byte[] b = new byte[2048];
int leng = 0;
while((leng = is.read(b)) != -1){
    os.write(b,0,leng);
}

 

[추가 - IE에서의 인코딩 문제 해결]

위와 같이 구현한 경우 chrome에서는 문제가 없으나 IE에서 실행할 경우 톰캣에서 아래와 같은 에러 발생

Error parsing HTTP request heaader

Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC3986

 

 

jsp 에서 아래와 같이 encodeURI(fileName) 해주어야 해결.

$(document).ready(function(){
    $('#fileDown').click(function(){

        var filename = $('#fileName').val();
        window.location.assign('${ctx}/infoCenter/download.do?fileName='+encodeURI(fileName));
    });
});

 

 

반응형

댓글

💲 추천 글