strutsのFormFileValidator
strutsにはファイルをアップロードするFormFileなるインターフェースが存在する。このFormFileをチェックするvalidatorがないっぽいので、それを作成した時のメモ。
独自のvalidatorは以前に記事を書いているのでそちらを参照するとして、具体的にソースなどを記載しておきます。
FormFileChecksクラスを作成。
まずはチェックをするロジックを作成します。作成する内容はファイルの拡張子をチェックすることにします。
注意することは、エラーが発生した場合にFormFileのメンバーをnullでクリアすることです。これを行っていないと、エラーがでたまま、再度、POSTすると異常終了するとかなんとか・・・
※FormFileのプロパティが2つ以上ある場合は、両方ともnullクリアする必要があるのかな・・・それなら、もう少し考えないといけないけど。
あとは、FormFile用のgetValueFormFileメソッドを作成していることぐらいですね。
package jp.digitalchild.struts.fw.validator; import java.lang.reflect.InvocationTargetException; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.validator.Field; import org.apache.commons.validator.GenericValidator; import org.apache.commons.validator.Validator; import org.apache.commons.validator.ValidatorAction; import org.apache.commons.validator.util.ValidatorUtils; import org.apache.struts.action.ActionMessages; import org.apache.struts.upload.FormFile; import org.apache.struts.validator.Resources; /** * ファイルチェック用のValidator * */ public class FormFileChecks { /** * ファイルの拡張子をチェックする。 * * @param bean * @param va * @param field * @param errors * @param v * @param request * @return */ @SuppressWarnings("deprecation") public static boolean validateFileType(Object bean, ValidatorAction va, Field field, ActionMessages errors, Validator v, HttpServletRequest request) { // ファイルの取得 FormFile value = null; try { value = getValueFormFile(bean, field.getProperty()); } catch(Exception e){ return false; } // 値が正しく取得できた場合は、チェック処理 if(value != null && value.getFileSize() != 0) { String[] fileStrings = value.getFileName().split(Pattern.quote(".")); String extentioin = fileStrings[fileStrings.length-1]; // 比較対象拡張子の読み込み String fileTypeList = field.getVarValue("FileType"); if(fileTypeList != null) { String[] candidates = fileTypeList.split(","); for (int cnt = 0; cnt < candidates.length; cnt++) { if (candidates[cnt].equalsIgnoreCase(extentioin)) { return true; } } } // 1つもマッチしない場合は、エラー処理 errors.add(field.getKey(), Resources.getActionMessage(request, va, field)); value = null; return false; } else { return true; } } /** * ファイルの拡張子をチェックする。(条件付き) * * @param bean * @param va * @param field * @param errors * @param v * @param request * @return */ public static boolean validateFileTypeIf(Object bean, ValidatorAction va, Field field, ActionMessages errors, Validator v, HttpServletRequest request) { Object form = v.getParameterValue("java.lang.Object"); FormFile value = null; boolean required = false; // 値の取得 try { value = getValueFormFile(bean, field.getProperty()); } catch(Exception e){ return false; } // 条件文の構文解析(strutsの標準ロジックと同じ) int i = 0; String fieldJoin = "AND"; if(!GenericValidator.isBlankOrNull(field.getVarValue("fieldJoin"))) { fieldJoin = field.getVarValue("fieldJoin"); } if(fieldJoin.equalsIgnoreCase("AND")) { required = true; } for(; !GenericValidator.isBlankOrNull(field.getVarValue("field[" + i + "]")); ++i) { String dependProp = field.getVarValue("field[" + i + "]"); String dependTest = field.getVarValue("fieldTest[" + i + "]"); String dependTestValue = field.getVarValue("fieldValue[" + i + "]"); String dependIndexed = field.getVarValue("fieldIndexed[" + i + "]"); if(dependIndexed == null) { dependIndexed = "false"; } String dependVal = null; boolean thisRequired = false; if(field.isIndexed() && dependIndexed.equalsIgnoreCase("true")) { String key = field.getKey(); if(key.indexOf("[") > -1 && key.indexOf("]") > -1) { String ind = key.substring(0, key.indexOf(".") + 1); dependProp = ind + dependProp; } } dependVal = ValidatorUtils.getValueAsString(form, dependProp); if(dependTest.equals("NULL")) { if(dependVal != null && dependVal.length() > 0) { thisRequired = false; } else { thisRequired = true; } } if(dependTest.equals("NOTNULL")) { if(dependVal != null && dependVal.length() > 0) { thisRequired = true; } else { thisRequired = false; } } if(dependTest.equals("EQUAL")) { thisRequired = dependTestValue.equalsIgnoreCase(dependVal); } if(fieldJoin.equalsIgnoreCase("AND")) { required = required && thisRequired; } else { required = required || thisRequired; } } // 条件が成立していれば if(required) { if(value != null && value.getFileSize() != 0) { String[] fileStrings = value.getFileName().split(Pattern.quote(".")); String extentioin = fileStrings[fileStrings.length-1]; // 比較対象拡張子の読み込み String fileTypeList = field.getVarValue("fileType"); if(fileTypeList != null) { String[] candidates = fileTypeList.split(","); for (int cnt = 0; cnt < candidates.length; cnt++) { if (candidates[cnt].equalsIgnoreCase(extentioin)) { return true; } } } // 1つもマッチしない場合は、エラー処理 errors.add(field.getKey(), Resources.getActionMessage(v, request, va, field)); value = null; return false; } else { return true; } } else { return true; } } /** * FormFile型でFormから値を取得 * * @param bean * @param property * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public static FormFile getValueFormFile(Object bean, String property) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { Object value = null; try { value = PropertyUtils.getProperty(bean, property); } catch (IllegalAccessException e) { e.printStackTrace(); throw e; } catch (InvocationTargetException e) { e.printStackTrace(); throw e; } catch (NoSuchMethodException e) { e.printStackTrace(); throw e; } return value == null?null:(value instanceof FormFile?(FormFile)value:null); } }
※条件付きのチェックについても、同様に作成しています。(validateFileTypeIf)
validator-rules.xmlへの追加
validator-rules.xmlに以下を追加します。内容についての説明は割愛。
<?xml version="1.0" encoding="UTF-8" ?> <form-validation> <global> <-- ここから下追加 --> <validator name="fileTypeCheck" classname="jp.digitalchild.struts.fw.validator.FormFileChecks" method="validateFileType" methodparams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, org.apache.commons.validator.Validator, javax.servlet.http.HttpServletRequest" depends="" msg="errors.fileTypeError"></validator> <validator name="fileTypeCheckIf" classname="jp.digitalchild.struts.fw.validator.FormFileChecks" method="validateFileTypeIf" methodparams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, org.apache.commons.validator.Validator, javax.servlet.http.HttpServletRequest" depends="" msg="errors.fileTypeError">%lt;/validator> <-- ここまで追加 --> </global> </form-validation>
validation.xmlへの追加
validation.xmlに以下を追加します。内容についての説明は割愛。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation// DTD Commons Validator Rules Configuration 1.1.3//EN" "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd"> <form-validation> <formset> <form name="sampleForm"> <field property="file" depends="fileTypeCheckIf"> <!-- ファイルタイプ --> <var> <var-name>fileType</var-name> <var-value>jpg,png,gif</var-value> </var> <!-- 条件:dependsをfileTypeCheckの場合、不要 --> <var> <var-name>field[0]</var-name> <var-value>checkbox1</var-value> </var> <var> <var-name>fieldTest[0]</var-name> <var-value>EQUAL</var-value> </var> <var> <var-name>fieldValue[0]</var-name> <var-value>1</var-value> </var> </field> </form> </formset> </form-validation>
その他
フォームの作成は、特に記載することはありません。プロパティとして、fileをFormFile型で定義すること、getter,setterを準備すること。
あとは、struts-config.xmlで、sampleFormのFormを定義すること。
この辺りは、strutsの基本なので、ここでは割愛します。
以上、簡単なメモでした。