ファイルアップロードのフォームでTextFieldなどの値が文字化けする
tapestry-uploadが壊れてます
MLのこの投稿で指摘されてるように、ファイルをアップロードしようとするとNullPointerExceptionが発生してしまいます。この投稿にあるように、springのCharacterEncodingFilterを使うと回避できます。
追記: Utf8Filterを、RequestFilterを実装するかわりにHttpServletRequestFilterを実装して、MultipartFilterの前に入れてやるのが正解っぽい。あとで詳しく書く。
http://d.hatena.ne.jp/butyricacid/20080105/1199519835
と書いたまま放置してしまっていましたが、というかMLに投稿してレスポンス付くの待ってたんだけど何もなくスルーされてしまった。。流量多くてすぐに流れちゃう上に文字コード絡みだと関心持つ人少ないからだろうか? 私の英文が通じてない?
ま、それはともかく詳しく書きます。
まず、ヌルポが出る問題自体は5.0.8ですでに直ってます。しかし、ファイルアップロードのフォームに他にフィールドがある場合、その値が文字化けします。Tapestry5Utf8Encoding の Utf8Filter を使っててもダメです(追記: wikiにアカウント作ってTapestry5Utf8Encodingに加筆してみました)。
そこで、tapestry-uploadの中を調べてみると次のことがわかりました。
ファイルアップロードのリクエストを処理する org.apache.tapestry.upload.internal.services.MultipartServletRequestFilter は org.apache.tapestry.services.HttpServletRequestFilter を実装していて、org.apache.tapestry.services.RequestFilter を実装している Utf8Filter よりも先に実行されてしまいます。そのためファイルアップロードのリクエストを処理する時点ではまだ、request.setCharacterEncoding("UTF-8") されておらず、request.getCharacterEncoding() はnullを返します。そしてこれがnullの時はフィールドの値はデフォルトエンコーディングでデコードするようになってます(5.0.7ではこのnullチェッックをしてなくてヌルポに)。
そんなわけで、以下のようにして Utf8Filter が MultipartServletRequestFilter より先に実行されるようにしたら文字化けしなくなりました。
- Utf8Filter は RequestFilter のかわりに HttpServletRequestFilter を実装するように変更
- その Utf8Filter を MultipartServletRequestFilter の前に追加
public HttpServletRequestFilter buildUtf8Filter() { return new HttpServletRequestFilter() { public boolean service(HttpServletRequest request, HttpServletResponse response, HttpServletRequestHandler handler) throws IOException { request.setCharacterEncoding("UTF-8"); return handler.service(request, response); } }; } public void contributeHttpServletRequestHandler( OrderedConfiguration<HttpServletRequestFilter> configuration, @InjectService("Utf8Filter") HttpServletRequestFilter utf8Filter) { configuration.add("Utf8Filter", utf8Filter, "before:MultipartFilter"); }
MultipartServletRequestFilter は MultipartFilter という名前で登録されているので、それの「前」を明示的に指定して Utf8Filter を追加するために、"before:MultipartFilter" という引数を渡しています。