Java Web - 下載中文檔名的檔案

基本上我們如果在前端點擊連結來直接下載中文檔案原則上是行不通的,因為點擊中文名的

當下,會被您的網頁指定的charset編碼做encoding,如%XX等等,如此一來就對應不到指定

的目錄檔案,也就無法下載到檔案了。

因此,在這邊是透過form的GET及POST來各別將您的中文檔名送到後端來進行檔案的輸出,

不過在這邊也仍需要注意編碼問題來進行適當的處理,否則下載下來的檔名可能會是亂碼!

PS. 拜讀良葛格的這篇文章,裡面有細部提到Servlet處理中文的流程,很有幫助喔!

1. 透過GET方式

前端 - HTML(contentType="text/html; charset=UTF-8")
<form action="/ExampleDemo/ProcessDownload" method="get" >
  <input type="submit" value="下載">
  <input type="hidden" name="file" value="念茲在茲-林杰樑醫師的諄諄教誨.pdf">
</form>

後端 - Servlet
String dst_fname = request.getParameter("file");
dst_fname = new String(dst_fname.getBytes("ISO-8859-1"), "UTF-8"); 
String name = java.net.URLEncoder.encode(dst_fname, "UTF-8");
response.setHeader("Content-Disposition","attachment;filename="+name);
FileInputStream fis = null;
int byteRead;
PrintWriter o = response.getWriter();
String url = request.getSession().getServletContext().getRealPath("/");
System.out.println(url+"doc\\"+dst_fname);
try {
   fis = new FileInputStream(url+"/doc/"+dst_fname);
   while ((byteRead = fis.read()) != -1) {
      o.write(byteRead);
   }
   o.flush();
} catch (Exception e) {
   e.printStackTrace();
} finally{
   if (fis != null) {
      fis.close();
   } 
}

當您從前端做submit之後,相關parameter值會進行UTF-8編碼(以上例來說)

請注意,依據良葛格該篇文章有提到

Tomcat在GET時,使用setCharacterEncoding()方法設定編碼就不會有作用

因此,會走預設的ISO-8859-1進行解碼,如此一來dst_fname就不會是"念茲在茲-林杰樑醫師

的諄諄教誨.pdf",因為前端是透過UTF-8編碼,如透過ISO-8859-1進行解碼應該是會有問題!

PS. 根據server.xml的設定,如果在Connector內的URIEncoding屬性沒指定的話,預設為

ISO-8859-1。

#本範例的server.xml設定
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"               redirectPort="8443" />

#官方URIEncoding說明
This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.

如此一來,可以透過new String(dst_fname.getBytes("ISO-8859-1"), "UTF-8"); 的方式

先將dst_fname進行ISO-8859-1編碼成一開始submit來的原值,再進行UTF-8的解碼

如此就可以得到"念茲在茲-林杰樑醫師的諄諄教誨.pdf",這樣子即可以取得正確的檔案位置!



2. 透過POST方式

前端code同上,只需將method的值改成POST

後端code同上,只需在一開始加上

request.setCharacterEncoding("UTF-8");
及拿掉dst_fname = new String(dst_fname.getBytes("ISO-8859-1"), "UTF-8");的處理即可!

留言