ICEfacesでファイルアップロード その2

ファイルアップロード自体は何も問題はないのだが、そのうちあることに気がつくはず。

マルチバイトキャラのファイル名は化けるのだ。

今回はこれに対処する。



ICEfacesのソースを軽くみてみるとどうやらJakarta Commons FileUploadを使っているらしい。

http://sventon.icefaces.org/svn/showfile.svn?path=%2ficefaces%2ftags%2ficefaces-1.7.2-SP1b%2ficefaces%2fcore%2fsrc%2fcom%2ficesoft%2ffaces%2fwebapp%2fhttp%2fcore%2fUploadServer.java&revision=HEAD&name=repo

一応文字コードの考慮はしているのだが、ヘッダの文字コードは現実的にnullのため、ここがうまくいかないようだ。そしてnullといいつつ、クライアントはUTF-8エンコードをするのに対して、ICEfacesはnullだったらデフォルトプラットフォームエンコーディングだと解釈するようだ。

つまり、UTF-8がデフォルトのLinux等でしか開発をしていないとこの辺は気がつきにくいかもしれない。だからこそおいらは文字コードがすぐに問題になりやすいWindowsで開発を続けている原因でもあるのだが。


ICEfacesが利用しているのは上のコードを見る限りここのようだ。

http://commons.apache.org/fileupload/apidocs/org/apache/commons/fileupload/servlet/ServletFileUpload.html#getItemIterator(javax.servlet.http.HttpServletRequest)

つまり、このへんを上書きしてあげればよいということになる。ICEfaces側のコードではなく、Commons FileUploadのコードにパッチを当てるというわけだ。

「org.apache.commons.fileupload.servlet」というパッケージを作成し、Commons FileUploadのServletFileUploadのソースをコピーしてくる。

そして一番下にあるメソッドを以下のように修正する。

public FileItemIterator getItemIterator(HttpServletRequest request)
        throws FileUploadException, IOException {

    ServletRequestContext src = new ServletRequestContext(request){

        @Override
        public String getCharacterEncoding() {
            return "UTF-8";
        }

    };

    return super.getItemIterator(src);
}

実行!

うん、ちゃんと変換できてる。Firefox3とIE6で確認したがたぶん大丈夫。


Commons FileUploadのコードを見てみたが、Javaのバージョンがかなり古いのを対象にしているために今じゃ信じられないコードとなっている。FileItemIterator とかも今の時代だとひどいコードということになる。

そしてICEfacesも意外とGenericsガンガン使っていないのに驚いたり。修正修正できてるから仕方がないのかな?小さいバージョンアップでも中身が大きく変わるようなのでICEfaces側のコードはいじらないほうがよさそうだ。


ほとんどのファイルアップロードは手軽に扱うためにFileUploadを利用しているところが多いと思う。だからあんまりこの辺は気にしてないのかもしれないけど。ICEfacesはFileItemStreamがわたってくる。これはアップロードの経過をAJAXでお知らせできるようにするためのもの。このへんも説明していきたい。アップロード中の経過が%で表示されないとかプアなインターフェースは今後駆逐されると思うのでこういう見た目は重要だと思う。