2013-03-25

透過 HttpServletResponse 下載中文檔名出現亂碼

ㄚ兜仔的作法:
@RequestMapping("/download")
public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {
  UploadVO uv = null; // TODO
  response.setContentType(uv.getFileType());
  response.setHeader("Content-disposition", "attachment;filename=" + uv.getFileName());
  ServletOutputStream out = response.getOutputStream();
  IOUtils.copy(new FileInputStream(uv.getFilePath()), out);
  out.flush();
  out.close();
}
檔名是 ISO8859-1 認識的字元沒問題,一旦遇到其他字元集,例如中文,還是可以下載,只是中文字都會變成空白或亂碼。

Google 到的解答有點討厭,作法因瀏覽器而異,IE、Firefox 與 Chrome 都不一樣,其他瀏覽器就不知道了。
private String encodeFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
  String userAgent = request.getHeader("user-agent");
  String encodedFileName;
  // IE
  if (StringUtils.contains(userAgent, "MSIE")) {
    encodedFileName = URLEncoder.encode(fileName, "utf-8");
  }
  // Firefox
  else if (StringUtils.contains(userAgent, "Firefox")) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < fileName.length(); i++) {
      char c = fileName.charAt(i);
      // Firefox 會自空白處切斷,所以將空白轉為+
      if (((int) c) < 128) {
        sb.append(URLEncoder.encode(String.valueOf(c), "ISO8859-1"));
      }
      else {
        sb.append(new String(String.valueOf(c).getBytes(), "ISO8859-1"));
      }
    }
    encodedFileName = sb.toString();
  }
  // Chrome
  else {
    encodedFileName = MimeUtility.encodeWord(fileName, "utf-8", "Q");
  }
  return encodedFileName;
}
挺頭痛的解法。
---
---
---

2 則留言: