中国語名ファイルダウンロードブラウザ互換処理


前言


ファイルダウンロード機能におけるファイル名の処理は、これまた古い問題であり、ネットワーク上でも様々な解決策があるが、それぞれのプロジェクト言語や符号化によって多くの案が気に入らない可能性がある.最近またこの問題に遭遇したので、一応自分の環境や符号化に基づいてまとめてみる
後続の観点は以下の環境に基づいている.
  • サービス言語:JAVA
  • プロジェクトコード:GBK
  • アプリケーションサーバResin 3.1
  • ぶんせき


    Firefoxはスペースの問題を切り捨てます


    Firefoxでは、ファイル名にスペースがある場合、スペースの後ろの部分の文字がブラウザで切り取られ、クライアントは完全なファイル名を取得できません.
    ソリューション:
  • ファイル名を二重引用符で囲む
  • MimeUtilityを使用する.EncodeWord(filename)メソッドでは、"=?gb 2312?B?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    IE 6ではリクエストヘッダの長さに制限があり、ファイル名の長さは150バイト程度しかありません


    テストによると、IE 6でダウンロードするファイル名の長さが150バイトを超えると、オーバー部分はブラウザに切り取られ(拡張子が完全であることを保証するためにブラウザが前から切り取られる)、中国語であれば文字化けしてしまう可能性があり(符号化後に切り取った後に再び中国語文字に復元できないはず)、これはIE 6自身のメカニズムである.したがって、短いファイル名を使用するか、コードを使用して合理的に切り取るしかありません.

    文字化けしについて


    これは私も十分に理解しているわけではありません.私の理解について簡単に分析してみましょう.
    まず、中国語はマルチバイト文字であることはよく知られているが、コンピュータの基本記憶手段はバイト(byte)であるため、1つのbyteは明らかに中国語を含むすべての文字を表すことができないため、中国語、日本語などの言語は記憶時に複数のバイトとしてコンピュータに格納され、表示時に対応する復号表示であればよい.
    そして、ネットワーク転送の単位もバイトであるためjava中の文字列は、転送前に手作業で符号化しないとオペレーティングシステムの符号化フォーマットでデフォルトで符号化され、クライアントに行ってデフォルトフォーマットで復号され、いずれも中国語環境であれば通常問題はないが、両方のデフォルト符号化が一致しないと符号化が起こりやすくなり、したがって、特定の符号化および復号フォーマットを手動で指定することを推奨します.
    ファイルのダウンロードについては、クライアントによってブラウザによって識別される符号化が異なりますが、基本的にはUTF-8符号化およびISO-8859-1符号化が識別されています.後者はfirefoxでは識別できません.また、ファイル名が中国語でないと遮断されることもありますので、UTF-8符号化を採用します.

    最後に、コードを貼り付けます


    他の機能が分割されたため、貼り付けられず、コア部分のコードはここにあります.
    次のコードはIE 6-9、firefox、chromeテストで正常にダウンロードできます.
    String us = request.getHeader("user-Agent");
    if(ua!=null){
        ua = ua.toLowerCase();
        //IE6 
        if(ua.contains("msie 6")){
            // ,encode +, %20
         //getSubStr 150 filename = URLEncoder.encode(getSubStr(filename),"utf-8").replaceAll("\\+","20%"); }else if(ua.contains("firefox")){ // =?gb2312?B?xxxxxxxx?= ,firefox , , filename = MimeUtility.encodeWord(filename,"utf-8","B");
    response.setHeader("Content-disposition", "attachment; filename=\"+filename+\"");
        }else{
     filename = URLEncoder.encode(filename,"utf-8").replaceAll("\\+","20%"); } } response.setContentType("application/x-download;"); response.addHeader("Content-Disposition",filename) OutputStream out = response.getOutputStream(); out.write(contents); out.flush()

     
    参考資料:http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http