hatora's blog

日常の出来事や仕事のことなど/Java/開発/Web/IT

Strutsとcommons fileuploadのお話

みんな大好きStrutsのお話。対象VerはStruts1.1です。

commons fileupload

commons fileuploadはStruts1.1標準の1.0。

ファイルをアップロード(Multipart)した際、Struts側ではFormFileが利用されています。
ファイルの情報を持つオブジェクト→FormFileといった感じです。
このFormFile、commons-fileuploadを利用して生成されます。


流れは以下
RequestProcessor#populate → RequestUtils#populate → MultipartRequestHandler#handleRequest → DiskFileUpload#parseRequest →
MultipartRequestHandler#addFileParameter


ソースを読むとわかりますが、
「commons-fileupload:FileItem → Struts側:FormFile」な形でラップしています。
※FileItemはファイル情報用のオブジェクトではありません。

MultipartRequestWrapperとCommonsMultipartRequestHandler

Multipartなリクエストの場合、HttpServletRequestはMultipartRequestWrapperとしてラップされます。
そして注目すべきは以下のメソッド。

    /**
     * This method does nothing.  To use any Servlet 2.3 methods,
     * call on getRequest() and use that request object.  Once Servlet 2.3
     * is required to build Struts, this will no longer be an issue.
     */
    public void setCharacterEncoding(String encoding) {
        ;
    }

RequestProcessorを継承したクラスやprocessPreprocessなんかでMultipartRequestWrapper#setCharacterEncoding
を呼び出すと、エンコード指定が無視されます。


そしてCommonsMultipartRequestHandlerの以下のメソッド。

    protected void addTextParameter(HttpServletRequest request, FileItem item) {
        String name = item.getFieldName();
        String value = null;

        try {
            value = item.getString(request.getCharacterEncoding());
        } catch (Exception e) {
            value = item.getString();
        }
       ・
       ・

item.getStringがnullとなり、item.getString()が呼ばれます
※FileItem#getStringはプラットフォームのデフォルトエンコード設定となります。


怖いですね、これ。
依存ライブラリ変更せず、Struts1.1そのまま使ってればこの設定になります。
画面側のエンコードは基本UTF-8なので、問題無く動いているように見えるだけです。

さいごに

Strutsは使うのやめましょう