1. 程式人生 > >ZK框架檔案下載檔名亂碼問題(空格,#截斷)解決

ZK框架檔案下載檔名亂碼問題(空格,#截斷)解決

在Java的web開發中,檔案下載功能的檔名檔名亂碼問題是經常遇到的。
對於這個問題,不同的瀏覽器,解決的方法不太一樣。
IE的話,通過URLEncoder對filename進行UTF8編碼。
而其他的瀏覽器(firefox、chrome、safari、opera),則要通過位元組轉換成ISO8859-1了。
所以對此要在後臺獲取瀏覽器型別(主要識別是否是IE)從而使用不同的編碼方法

    //檔案下載
    @SuppressWarnings({ "unchecked", "deprecation" })
    @Command
    public void fileDownLoad() throws UnsupportedEncodingException
    {
        if(checkListitems==null||checkListitems.size
()==0) { Messagebox.show("請選擇下載的檔案","提示", Messagebox.OK, Messagebox.INFORMATION); return; } Iterator it=checkListitems.iterator(); Map<String,Object> selectMap=(Map) it.next(); String filePath=selectMap.get("file_path")+""
; String fileExtension=filePath.substring(filePath.lastIndexOf(".")); String enCodeName=(String)selectMap.get("file_name"); if(!enCodeName.endsWith(fileExtension)) { enCodeName=enCodeName+fileExtension; } //檔案亂碼問題相容IE HttpServletRequest request =(HttpServletRequest) Executions.getCurrent
().getNativeRequest(); String header = request.getHeader("User-Agent").toUpperCase(); if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) { enCodeName = URLEncoder.encode(enCodeName, "utf-8"); enCodeName = enCodeName.replace("+", "%20"); //IE下載檔名空格變+號問題 enCodeName = enCodeName.replace("#", "%23"); //遇到#截斷問題 } else { enCodeName=new String(enCodeName.getBytes("UTF-8"), "ISO-8859-1"); //enCodeName = enCodeName.replace("#", "%23");//這裡設定不成功 } File file=new File(MisUtils.getWebRootDir()+filePath); InputStream is=null; try { is = new FileInputStream(file); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); Messagebox.show("未找到對應檔案!", "錯誤", Messagebox.OK, Messagebox.ERROR); return; } if(file.exists()) { //Filedownload. save(is, null, enCodeName); AMedia media=new AMedia(enCodeName, fileExtension.substring(1), null, is); Clients.response(new AuDownload(Executions.getCurrent().getDesktop().getDownloadMediaURI( media, enCodeName).replace("+", "%2B").replace("#", "%23"))); } }

到此IE瀏覽器可以輕鬆解決檔名包含#或空格轉成+號問題
但是,chrome等瀏覽器使用的是另外一種編碼方式ISO8859-1
這個編碼方式並不對+或#編碼,導致檔案下載時伺服器後臺還是對+或#當成了特殊的符號處理,從而導致下載檔名不對或被截斷。

在此附上相關特殊字元的十六進位制編碼

url出現了有+,空格,/,?,%,#,&,=等特殊符號的時候,可能在伺服器端無法獲得正確的引數值,如何是好?
解決辦法
將這些字元轉化成伺服器可以識別的字元,對應關係如下:
URL字元轉義
用其它字元替代吧,或用全形的。
+ URL 中+號表示空格 %2B
空格 URL中的空格可以用+號或者編碼 %20
/ 分隔目錄和子目錄 %2F
? 分隔實際的URL和引數 %3F
% 指定特殊字元 %25
# 表示書籤 %23
& URL 中指定的引數間的分隔符 %26
= URL 中指定引數的值 %3D

由於利用chrome下載時使用的是ISO-8859-1對#和+並沒有編碼所以利用Filedownload. save(is, null, enCodeName); 伺服器還是對特殊符號解碼導致錯誤
為了解決這個問題需要從新使用新的方法再給特殊字元編碼(注意在ISO8859-1編碼後把#replace到%23不成功)
解決如下(把filedownload替換成下面程式碼):

//enCodeName為檔名,第二個引數是副檔名如txt,第三個引數是contenType如text/plain可使用null(取預設),第四個是檔案的流
AMedia media=new AMedia(enCodeName, fileExtension.substring(1), null, is);
//對download的uri所含有的特殊字元進行替換編碼
Clients.response(new AuDownload(Executions.getCurrent().getDesktop().getDownloadMediaURI(
                    media, enCodeName).replace("+", "%2B").replace("#", "%23")));

在這裡丟擲一個疑問:如果普通的JavaWeb(不是使用ZK)使用非IE下載該如何解決這個問題?(

    response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");
        response.setHeader("Content-Length", String.valueOf(fileLength));

參考:
http://blog.csdn.net/lisehouniao/article/details/52550539
https://stackoverflow.com/questions/47549771/zk8-filedownload-save-cut-filenames#

感謝ZK的Jean Yen ,在這裡在此謝謝您的幫助,祝願ZK越來越好
Thanks,
Hungly