Strutsによるファイルのアップロード

サーブレット/JSPでファイルのアップロードを実装するには、 Jakarta Commons FileUploadパッケージが便利です。 が、特にStrutsでは、そのFileUploadを用いて、独自のクラスライブラリが出来ているので、 そちらを使うとよいでしょう。 このページのソースはStruts 1.1で動作確認しました。 なおJakarta Commons FileUploadについてはJava小技の部屋でご紹介しています。


ファイル名を入力するJSP

<%@ page language="java" contentType="text/html;charset=Windows-31J" %>
<%@ taglib prefix="html" uri="/WEB-INF/struts-html.tld" %>

<html><body>
<html:form action="/FileUploadEx" focus="fileName" enctype="multipart/form-data">
  ファイル:<html:file property="fileName" size="40"/><br>
  <html:submit value="登録"/>
</html:form>
</body></html>

ファイル名を入力する要素はhtml:fileタグで指定します。 html:formタグには enctype="multipart/form-data" の指定が必須です。 これはサーブレットやStrutsに限らず、CGIでも同様ですね。


結果を表示するJSP(ほぼ意味なし)

<%@ page language="java" contentType="text/html;charset=Windows-31J" %>
<%@ taglib prefix="html" uri="/WEB-INF/struts-html.tld" %>

<html><body>
処理を行いました。
<pre>

</pre>
</body></html>

アップロードの処理後、処理結果を表示するページです。


Strutsアクションクラス

/*
 * FileUploadExAction
 * 2004/07/04
 */
package testcl01.struts.action;

import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.*;
import org.apache.struts.upload.*;
import ushi.wui.WebFileNameUtil;

/**
 * リクエスト・パラメータでアップロードされたファイルを受け取り、
 * workディレクトリの下に格納します。
 */
public class FileUploadExAction extends Action {

    /**
     * パス修飾のあるファイル・パスから、パス修飾を削り、ファイル名だけを返します。
     * 具体的には、パスの最後の/または\よりも後ろの部分だけを返します。
     * 最後の文字が区切り文字だった場合、空文字列が返ります。
     * @param path
     * @return
     */
    private static String getBaseName(String path) {
        int index1 = path.lastIndexOf('\\');
        int index2 = path.lastIndexOf('/');
        int index;
        if (index1 == -1) {
            if (index2 == -1) {
                // 区切り文字が現れなかったので、そのまま返す
                return path;
            } else {
                index = index2;
            }
        } else {
            if (index2 == -1) {
                index = index1;
            } else {
                // 区切り文字が両方あったので、より後ろの方を採用
                index = (index1 > index2) ? index1 : index2;
            }
        }
        return path.substring(index + 1);
    }

    /**
     * リクエスト・パラメータを受け取り処理をします。
     */
    public ActionForward execute(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {

        DynaActionForm fb = (DynaActionForm) form;
        FormFile ff = (FormFile) fb.get("fileName");

        /* 出力先ディレクトリの確定 */
        WebFileNameUtil wu = new WebFileNameUtil(getServlet().getServletContext(), request);
        String storeDir = wu.getRealPath("/work");
        String clientFileName = ff.getFileName();

        long size = ff.getFileSize();
        InputStream is = ff.getInputStream();
        
        if (size > 0) {
            String outputPath = storeDir + "/" + getBaseName(clientFileName);

            OutputStream bos = new FileOutputStream(outputPath);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.close();
        }

        return mapping.findForward("success");
    }
}

アクションクラスです。 アップロードされたファイルに関する情報は、 org.apache.struts.upload.FormFileオブジェクトで取り出すことができます。 WebFileNameUtilなる謎のクラスがありますが、これは単に、 コンテキストルートからの相対パスをWebサーバのファイルシステム上の絶対パスに変換しているものです。 それで、FormFile#getInputStream() で取得した入力ストリームの内容を、 出力ストリームを開いてどこかに書き出せばアップロード処理は完了です。 なお、このFormFileはインターフェースで、実際の実装には Jakarta Commons FileUploadのパッケージが使われています。 FileUploadパッケージには、FileItem#write(java.io.File)メソッドという、 呼び出しひとつでアップロードされたファイルの内容をWebサーバのファイルシステム上に保存できるユーティリティ・メソッドがあって便利に使えるのですが、 StrutsのFormFileの実装ではそのメソッドは遮蔽されているので、 このサンプルのように自分でIO処理を書く必要があるようです。 上記のコードは、 Strutsのソース配布に同梱のその名もUploadActionクラスのソース・コードを見ながら作りました。


struts-config.xmlへの記述

<form-bean name="FileUploadExForm" type="org.apache.struts.action.DynaActionForm">
    <form-property name="fileName" type="org.apache.struts.upload.FormFile" />
</form-bean>
...
<action path="/FileUploadEx"
    attribute="FileUploadExForm" name="FileUploadExForm"
    type="testcl01.struts.action.FileUploadExAction">
    <forward name="success" path="/fileupload02.jsp" />
</action>

そしてstruts-config.xmlですが、html:fileタグに対応するプロパティ(ここではfileName)のクラスには、 org.apache.struts.upload.FormFileを指定する必要があります。 うっかりjava.lang.Stringなどにしないように大注意。 actionの方は問題ないでしょう。 が、FormFileはシリアライザブルなオブジェクトではありません。 従ってここでは書いていませんが、scopeをsessionにしていると、 サーブレット・コンテナの上げ下げの際に、シリアライズできないなどの警告が出るので、 明示的にrequestを指定した方がいいかもしれません。

Server Side Java Index Top

(first uploaded 2004/07/04 last updated 2004/07/04, URANO398)

楽天モバイル[UNLIMITが今なら1円] ECナビでポインと Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!


無料ホームページ 無料のクレジットカード 海外格安航空券 解約手数料0円【あしたでんき】 海外旅行保険が無料! 海外ホテル