<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Mongoose House

    Technical Edition

    統計

    留言簿(4)

    積分與排名

    閱讀排行榜

    Unicode網頁中上傳下載文件時發生文件名亂碼的問題

    最近有一個需要支持unicode的項目在上傳和下載文件時遇到文件名亂碼問題. 項目背景, 這個項目關鍵之處在于需要支持unicode以及支持Micorosoft Internet Explorer和Netscape Navigator兩種瀏覽器. 為了解決這個問題, 我使用以下環境進行了嘗試.

    J2SE : 1.5.0_04
    Tomcat : 5.5.17
    Microsoft Internet Explorer 6.0 with SP2
    Netscape Navigator 7.1
    Firefox 1.5
    以及Struts 1.1 (這個基本上對此次測試不是非常重要)

    上傳文件

    對于unicode的頁面進行上傳文件的時候, 我使用一個text box和一個file upload box來進行比較. 頁面如下.

    utf-8 upload page

    ?通過此頁面進行文件上傳后, IE, NC以及FF所傳輸的數據均相同. 如下

    Content-Type:?multipart/form-data;?boundary=---------------------------282302224217945
    Content-Length:?27980

    -----------------------------282302224217945
    Content-Disposition:?form-data;?name="theText"

    C:\縺ゅ≠縺ゅ≠.xls
    -----------------------------282302224217945
    Content-Disposition:?form-data;?name="theFile";?filename="縺ゅ≠縺ゅ≠.xls"
    Content-Type:?application/vnd.ms-excel

    可以看出, 對text box和file upload box中的文件名所有瀏覽器均采取了相同的編碼. 經證實, 是上傳頁面的編碼方式——所有瀏覽器均對unicode數據(utf-8)采取了本地的編碼方式(這里是ms932).

    在服務器端對上傳的數據進行解碼.

    解碼的方式有很多, 這里我使用最普遍以及正規的request.setCharacterEncoding的方法. 發現form表單中的text box可以被正常解碼, 但是file upload box中的文件名無法通過這種方式解碼. 所以只能使用手工解碼.

    String?fixedFileName?=?new?String(fileName.getBytes("SJIS"),?"UTF-8");

    其中SJIS是客戶端系統的編碼, UTF-8是客戶端頁面的編碼.

    上傳文件測試中, 所有瀏覽器表現一致, 需要注意的是文件名和表單數據的不同處理方式.

    下載文件

    使用一個unicode的JSP頁面, 在頁面上有一個固定的超鏈接, 傳遞給服務器一個文件名. 服務器依照這個文件名把服務器端的文件傳遞給客戶端.

    下載頁面

    <%@?page?language="java"?contentType="text/html;?charset=utf-8"%>

    <meta?http-equiv="content-type"?content="text/html;?charset=utf-8">

    <a?href="download.do?name=ああああ.xls">ダウンロード</a>

    對于這樣一個頁面, 當點擊超鏈接后, 各瀏覽器處理方式不同

    IE會把超鏈接依照頁面當前編碼方式編碼(這里是utf-8)后, 發送給服務器端

    GET?/nsupload/download.do?name=縺ゅ≠縺ゅ≠.xls?HTTP/1.1

    NC和FF會把超鏈接依照頁面編碼方式編碼(這里是utf-8)后, 再通過url encoding后, 發送給服務器端

    GET?/nsupload/download.do?name=%E3%81%82%E3%81%82%E3%81%82%E3%81%82.xls?HTTP/1.1

    (經證實, E38182是「あ」的unicode代碼)

    在服務器收到提交的數據后, 需要對其進行解碼. 需要注意的是這種方式下使用request.setCharacterEncoding無效. 所以必須手工解碼.

    name?=?new?String(name.getBytes("ISO-8859-1"),?"UTF-8");

    其中ISO-8859-1是Tomcat服務器的特性, Tomcat會把所有的數據先轉換為ISO-8859-1的形式. UTF-8是實際的編碼方式.

    在得到文件名后, 就可以正確地讀取文件, 然后把文件傳遞給客戶端了. 其中, 文件名是保存在Http報頭(header)的Content-Disposition中.

    response.setHeader("Content-Disposition",?"inline;?filename="?+?_filename);
    //或者
    response.setHeader("Content-Disposition",?"attachment;?filename="?+?_filename);

    經實驗證明, 使用inline或者attachment對文件名的編碼方式沒有影響.

    另外一個需要設置的是Content-Type.

    response.setContentType("application/vnd.ms-excel");
    //或者
    response.setContentType("application/vnd.ms-excel;?charset=UTF-8");
    //或者
    response.setContentType("application/x-download; name=" + _filename);

    經試驗證明, 使用application/*的任何形式都對文件名的編碼方式沒有影響.
    第二點, 經試驗證明, 這里的charset設置會被三種瀏覽器忽略, 所以設置與否影響文件名的編碼方式.
    第三點, 經試驗證明, 這里的name設置對文件名沒有任何影響.

    可能還有一個屬性需要注意, 就是Content-Language. 經試驗證明, Content-Language有無, 或者為何值, 對文件名沒有任何影響.

    那么對于non-ascii的文件名如何操作才可以保證客戶端可以得到正確的顯示呢?

    經過調查, 有三種方法(在網上搜索后認為可能這篇文章是對于這個問題探討最深入的文章)

    第一, 使用URLEncoding方法. 即對文件名進行URLEncoding.

    name?=?URLEncoder.encode(name,?"UTF-8");


    這種方式適用于IE, 但是不適用于NC和FF. 在這種方式下, 網絡上傳輸的是url encoding后的ascii編碼.

    Content-Disposition:?inline;?filename=%E3%81%82%E3%81%82%E3%81%82%E3%81%82.xls

    NC和FF不能對這樣的文件名進行有效的解碼.

    NC download

    FF download

    第二, 使用字符串字符集強行轉換為本地字符集方法, 這樣做的原理是JVM底層全部為unicode. 所以一旦一個字符串表示了正確的字符集而被存儲后, 這個字符串會被轉換為任意字符集.

    原理二是, IE和FF對非url encoding的non-ascii文件名采用客戶端系統本地的編碼方式進行轉換.

    name?=?new?String(name.getBytes("Shift_JIS"),?"ISO-8859-1");

    需要注意的是, 這里的name原本是utf-8的.

    在網絡上傳輸的為

    Content-Disposition:?inline;?filename=ああああ.xls


    經過試驗, IE和FF支持這種方式, NC不支持. 表現為NC無法解析文件名.

    第三種, 使用Base64編碼文件名. 原理是這種做法符合RFC2047的定義.

    name?=?javax.mail.internet.MimeUtility.encodeText(name,?"UTF-8",?"B");

    使用到了JavaMail中的Base64編碼的類MimeUtility.

    在網絡上傳輸的為經過Base64編碼的ascii字符.

    Content-Disposition:?inline;?filename==?UTF-8?B?44GC44GC44GC44GCLnhscw==?=

    只有FF支持這種方式, IE表現為無法解析文件名, NC表現為忽略Base64編碼.

    NC base64 download

    IE Base64 download

    以上三種方法是目前來講, 使瀏覽器可以正確下載non-ascii文件名的方法. 其中IE支持兩種(url encoding和force transform), FF支持兩種(force transform和base64 encoding), NC一種都不支持.

    關于這次調查的結果, 對于NC多說兩句, 我以為這個結果是由于NC 7.1和Tomcat 5.5不兼容造成的. Tomcat 5.5要求必須把所有報頭先轉變為ISO-8859-1的格式, 而NC 7.1卻無法直接對ISO-8859-1進行正確的解析或者說是解析功能比較弱. 如果有時間, 我會繼續驗證非unicode的情況以及NC 8的情況.


    ---2006年9月14日21:00 補充---

    在NC 8.1上進行了測試, 測試結果是NC 8.1支持方法三, 即base64 encoding.

    nc81-base64-down.jpg

    posted on 2006-09-14 20:43 Mongoose 閱讀(10713) 評論(3)  編輯  收藏

    評論

    # re: Unicode網頁中上傳下載文件時發生文件名亂碼的問題 2006-09-14 20:48 Mongoose

    一篇關于這個問題的thread. 作為memo記錄在此, 雖然我的測試結果和thread上的結果不盡相同. —— 可能是瀏覽器版本和字符集的關系.
    http://forum.java.sun.com/thread.jspa?threadID=696263  回復  更多評論   

    # re: Unicode網頁中上傳下載文件時發生文件名亂碼的問題 2006-09-25 15:11 Mongoose

    我們經常在處理亂碼問題的時候看到的都是"??", 為了能更有效地處理亂碼問題, 有一個best practise就是打印一個字符串的byte code. 由于一個字符串在Java內部都是已Unicode存儲, 所以打印的時候需要指定此字符串的encoding.
    ---
    public static void printbyte(String str, String enc) throws Exception{
    System.err.print("STR[" + str + "]-->[");
    byte[] b = str.getBytes(enc);
    for(int i = 0; i < b.length; i++) {
    System.err.print(b[i]);
    }
    System.err.println("]" + enc);
    }  回復  更多評論   

    # re: Unicode網頁中上傳下載文件時發生文件名亂碼的問題 2007-10-03 12:53 metal

    這篇文章很棒!支持一下。  回復  更多評論   


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 三年片免费观看大全国语| 在线观看肉片AV网站免费| 国产AV无码专区亚洲AWWW| 国产免费一区二区三区不卡| 综合自拍亚洲综合图不卡区| 成人激情免费视频| 国产精品极品美女自在线观看免费| 亚洲人成在线电影| 日本免费观看网站| 国产激情免费视频在线观看| 亚洲国产精品成人AV在线| 亚洲av色福利天堂| 午夜爱爱免费视频| 七色永久性tv网站免费看| 亚洲第一成年网站视频| 亚洲国产精品无码久久久秋霞2| 欧亚精品一区三区免费| 久久精品国产免费| 成人婷婷网色偷偷亚洲男人的天堂| 日本亚洲欧洲免费天堂午夜看片女人员| 国产片AV片永久免费观看| 美女无遮挡拍拍拍免费视频| 亚洲AV男人的天堂在线观看| 亚洲国产精品乱码一区二区| 免费观看的毛片手机视频| 久久精品国产大片免费观看 | 日韩大片免费观看视频播放| 久久亚洲私人国产精品vA| 婷婷综合缴情亚洲狠狠尤物| 91成人免费观看网站| 久久久精品免费国产四虎| 黄页网站在线观看免费| 亚洲一区二区三区免费观看| 亚洲第一AAAAA片| 亚洲一区二区三区免费| 国产精品极品美女免费观看| 两个人的视频高清在线观看免费| 久久久久国产免费| 中文字幕不卡免费视频| 日韩大片在线永久免费观看网站| 亚洲欧美日韩中文字幕一区二区三区|