프로그래밍 2017. 5. 22. 00:56



브라우저를 이용해 파일을 다운로드할 경우 인코딩 문제로인해 한글 및 특수문자 깨짐현상이 발생하죠!


이런문제를 해결하기 위해서는 첫 번째 Client가 사용하는 브라우저 확인이 필요합니다. 두 번째 브라우저별 파일명 인코딩 처리가 필요합니다.





1. 파일다운로드를 위한 컨트롤러 소스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RequestMapping(value="/notice/fileDownload")
    public void fileDownload(HttpServletRequest req, HttpServletResponse res, NoticeBean noticeBean) throws Exception{
        
        String fileStrNm = req.getParameter("fileStrNm");
        String fileOrgNm = req.getParameter("fileOrgNm");
        
        byte fileByte[] = FileUtils.readFileToByteArray(new File(path+ "/" +fileStrNm));
         
        String encodedFileName = FileUtil.getEncodedFileName(fileOrgNm, CommonUtil.getBrowser(req));
        res.setContentType("application/octet-stream");
        res.setContentLength(fileByte.length);
        res.setHeader("Content-Disposition""attachment; fileName=\"" +encodedFileName +"\";");
        res.setHeader("Content-Transfer-Encoding""binary");
        res.getOutputStream().write(fileByte);
         
        res.getOutputStream().flush();
        res.getOutputStream().close();
        
    }
cs



2. Client의 브라우저 확인


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static String getBrowser(HttpServletRequest request) {
   String userAgent = request.getuserAgent("User-Agent");
  
   if (userAgent.indexOf("MSIE"> -1 || userAgent.indexOf("Trident"> -1 ){
        //IE 버전 별 체크  >>  Trident/7.0(IE 11), Trident/6.0(IE 10) , Trident/5.0(IE 9) , Trident/4.0(IE 8)
        return "MSIE";
   } else if (userAgent.indexOf("Chrome"> -1) {
        return "Chrome";
   } else if (userAgent.indexOf("Opera"> -1) {
        return "Opera";
   } else if ( userAgent.indexOf("Firefox"> -1 ) {
        return "Firefox";
   }
   return "Safari";
}
cs



3. 브라우저별 파일명 인코딩 처리


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  // 파일 다운로드 시 Cilent의 브라우저에 따라 파일명의 인코딩 설정
    public static String getEncodedFileName(String filename, String browser) throws Exception {
        
           String encodedFilename = null;
           if (browser.equals("MSIE")) {
               // 한글 파일명 깨짐현상을 해결하기 위해 URLEncoder.encode 메소드를 사용하는데,
               // 파일명에 공백이 존재할 경우 URLEncoder.encode 메소드에의해 공백이 '+' 로 변환됩니다.
               // 변환된 '+' 값을 다시 공백으로(%20)으로 replace처리하시면 됩니다.
               // \\+의 의미는 정규표현식에서 역슬래시(\)는 확장문자로
               // 역슬래시 다음에 일반문자가 오면 특수문자로 취급하고 
               // 역슬래시 다음에 특수문자가 오면 그 문자 자체를 의미 
               // 기존 파일명에 있던 '+' 는 URLEncoder.encode() 메소드에 의해 '%2B' 로 변환이 됩니다.
                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 {
                                // ASCII문자(0X00 ~ 0X7E)는 URLEncoder.encode를 적용하지 않는다.     
                                  sb.append(c);
                          }
              }
              encodedFilename = sb.toString();
           } else {
              throw new RuntimeException("Not supported browser");
           }
           return encodedFilename;
    }
cs


위와 같이 처리하시면 파일 다운로드 시 파일명이 깨지는 현상을 방지할 수 있습니다.


posted by 생각퍼즐
: