対象読者
この記事を読むのに必要な知識を以下にまとめます。
- Java
- JavaScript
- jQuery、jQuery-ui
- HTML、CSS
必要な環境
dataforms.jarを使用した開発では、以下を使用しています。
- JDK1.8
- Eclipse 4.5以上
- Tomcat 7以上
ファイルのアップロード
前回の記事で使用したプロジェクトに新たなページ(FileUploadPage)を作成します。以下のFileUploadForm.java以外のソースは開発ツールを使用してひな形を作成し、太字の部分を追加コーディングしたものです。作成の手順は前回の記事を参照してください。
package pagesample.page; import dataforms.app.page.base.BasePage; import dataforms.dao.Dao; import dataforms.dao.Table; /** * ページクラス。 */ public class FileUploadPage extends BasePage { /** * コンストラクタ。 */ public FileUploadPage() { this.addForm(new FileUploadForm()); } /** * Pageが配置されるパスを返します。 * * @return Pageが配置されるパス。 */ public String getFunctionPath() { return "/pagesample"; } /** * 操作対象テーブルクラスを取得します。 * <pre> * ページjavaクラス作成用のメソッドです。 * </pre> * @return 操作対象テーブル。 */ public Class<? extends Table> getTableClass() { return Table.class; } /** * テーブルを操作するためのDaoクラスを取得します。 * <pre> * ページjavaクラス作成用のメソッドです。 * </pre> * @return Daoクラス。 */ public Class<? extends Dao> getDaoClass() { return Dao.class; } }
package pagesample.page; import java.io.File; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import dataforms.annotation.WebMethod; import dataforms.controller.Form; import dataforms.controller.JsonResponse; import dataforms.controller.Response; import dataforms.dao.file.FileObject; import dataforms.field.base.TextField; import dataforms.field.common.FolderStoreFileField; import dataforms.validator.RequiredValidator; import dataforms.validator.ValidationError; /** * ファイルアップロードフォーム。 * */ public class FileUploadForm extends Form { /** * コンストラクタ。 */ public FileUploadForm() { super(null); this.addField(new TextField("text1")).setComment("テキスト"); this.addField(new FolderStoreFileField("file1")).addValidator(new RequiredValidator()); } /** * Logger. */ private Logger logger = Logger.getLogger(FileUploadForm.class); /** * アップロードメソッド。 * @param p POSTされた情報。 * @return 応答情報。 * @throws Exception 例外。 */ @WebMethod public Response upload(final Map<String, Object> p) throws Exception { this.methodStartLog(logger, p); Response result = null; List<ValidationError> list = this.validate(p); if (list.size() > 0) { result = new JsonResponse(JsonResponse.INVALID, list); } else { Map<String, Object> d = this.convertToServerData(p); String text1 = (String) d.get("text1"); FileObject file1 = (FileObject) d.get("file1"); File f = file1.getTempFile(); logger.debug("text1=" + text1 + "file=" + f.getAbsolutePath()); result = new JsonResponse(JsonResponse.SUCCESS, ""); } this.methodFinishLog(logger, result); return result; } }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="mainDiv"> <form id="fileUploadForm"> <div class="formHeader">xxx</div> <table class="responsive"> <tbody> <tr> <th>テキスト</th> <td><input type="text" id="text1" /></td> </tr> <tr> <th>file1</th> <td><input type="file" id="file1"/></td> </tr> </tbody> </table> <button id="uploadButton" type="button">アップロード</button> </form> </div> </body> </html>
/** * @fileOverview {@link FileUploadForm}クラスを記述したファイルです。 */ /** * @class FileUploadForm * * @extends Form */ FileUploadForm = createSubclass("FileUploadForm", {}, "Form"); /** * HTMLエレメントとの対応付けを行います。 */ FileUploadForm.prototype.attach = function() { Form.prototype.attach.call(this); var thisForm = this; this.find("#uploadButton").click(function() { thisForm.upload(); }); }; /** * アップロードボタンの処理。 */ FileUploadForm.prototype.upload = function() { // エラー情報をクリアする。 currentPage.resetErrorStatus(); if (this.validate()) { var thisForm = this; this.submit("upload", function(r) { if (r.status == ServerMethod.INVALID) { // サーバーのバリデーション結果を表示する。 currentPage.setErrorInfo(thisForm.getValidationResult(r), thisForm); } else if (r.status == ServerMethod.SUCCESS) { // TODO:成功時の処理を実装。 logger.log("json=" + JSON.stringify(r)); } }); } };
今回使用したFolderStoreFileFieldクラスは、アップロードしたファイルをサーバー中のフォルダーに保存し、そのパスをデータベースのフィールドに記録するためのフィールドです。このページから「IMG_7021.JPG」というファイルをアップロードすると、サーバーのログは以下の通りになります。
2018-02-26 17:29:15,110 INFO DataFormsServlet - context=/pagesample, uri=/pagesample/pagesample/page/FileUploadPage.df 2018-02-26 17:29:15,110 INFO DataFormsServlet - classname=pagesample.page.FileUploadPage 2018-02-26 17:29:15,180 INFO DataFormsServlet - method=fileUploadForm.upload 2018-02-26 17:29:15,180 DEBUG Page - csrfToken=Vz2uGN96hkJrM6sbDojL0ZwsyXGrXB2WpGQvCaXQIBYIuXUA8pntnQ== 2018-02-26 17:29:15,181 INFO FileUploadForm - pagesample.page.FileUploadForm.upload start param={csrfToken=Vz2uGN96hkJrM6sbDojL0ZwsyXGrXB2WpGQvCaXQIBYIuXUA8pntnQ%3D%3D, text1=入力したテキスト, file1_fn=, file1=name=IMG_7021.JPG, StoreLocation=\tmp\upload__42259447_161d13aec07__8000_00000001.tmp, size=1599499bytes, isFormField=false, FieldName=file1} 2018-02-26 17:29:15,189 DEBUG FileObject - fileName=IMG_7021.JPG,fnPattern=(?i).*\.jpg$,contentType=image/jpeg 2018-02-26 17:29:15,189 DEBUG FileUploadForm - text1=入力したテキストfile=D:\uploadData\null\file1\-1\20180226172915181_IMG_7021.JPG 2018-02-26 17:29:15,190 INFO FileUploadForm - pagesample.page.FileUploadForm.upload finish result=dataforms.controller.JsonResponse@3bd8501a 2018-02-26 17:29:15,190 DEBUG JsonResponse - json={ "contentType": "text/plain; charset=utf-8", "result": "", "status": 0 }
FolderStoreFileFieldに対応したデータはFileObject型のデータとなっており、そのgetTempFile()メソッドでサーバーにアップロードされたファイルのパスを取得することができます。このログからアップロードされたファイルは、「D:\uploadData\null\file1\-1\20180226172915181_IMG_7021.JPG」というファイルに保存されていることがわかります。FolderStoreFileFieldに指定されたファイルは、サーバーの以下のパスに保存されます。
[web.xmlのupload-data-folderに設定されたパス]/[テーブル名]/[フィールドID]/[ユーザID]/[アップロード日時]_[ファイル名]
今回は、テーブルに配置したフィールドではないためテーブル名がnullとなっており、ログインせずにファイルをアップロードしたためユーザIDが-1となっています。FolderStoreFileFieldをテーブルに配置すると、そのテーブルに対するinsert/updateの実行でこのパスがテーブルに登録されます。
通常ファイルをアップロードするフォームには「enctype="multipart/form-data"」等の設定が必要になります。しかし今回作成したhtmlにはこの記述がありません。これでなぜファイルがサーバーにアップロードされるかというと、フォームのsubmitメソッドがフォーム中にファイルフィールドが存在した場合、自動的に「enctype="multipart/form-data"」を設定してからPOSTしているからです。さらにサーバーサイドではcommons-fileuploadを使用してサーバー中にファイルを展開し、その情報をFileObjectに設定します。このように、dataforms.jarはファイル送信の特殊な作法を意識する必要が無い構造をしています。