html5で複数ファイルアップロード(SAStruts)その2
チュートリアルに存在するファイルアップロードをベースとして機能を拡充していく。
前回の導入編により、画面こそそれっぽくなったけど、 実際にアップロードされるファイルが1件だけという問題が発生した。
今回は問題特定編。 処理の内部を見てみる。
まず、送るパラメータがファイルだけだと調査しにくいので、 html(JSP)にダミーでテキストフィールドを用意しておく
input.jsp
<%@page pageEncoding="UTF-8"%> <html> <head> <title>Tutorial: Upload</title> <link rel="stylesheet" type="text/css" href="${f:url('/css/sa.css')}" /> </head> <body> <h1>Tutorial: Upload</h1> <html:errors /> <s:form enctype="multipart/form-data"> <input type="file" name="formFile" multiple/><br/> <input type="text" name="dummyField" value="testValue1"/><br/> <input type="text" name="dummyField" value="testValue2"/><br/> <input type="submit" name="upload" value="アップロード" /> </s:form> </body> </html>
※ここでname="dummyField"が二つあるのはちょっとした布石。
早速試しに2ファイル選択した状態でsubmitしてみる。
そしてS2RequestProcessor#processPopulateの中で、いい感じのところで止める(抽象的) Strutsでパラメータの授受と言えばここしか思いつかん。
結果はこちら
テキストパラメータは配列になって複数のパラメータを認識しているのに対して、 ファイルパラメータは一つしか認識していない!
この違いはいったい何だろう!
さらにソースコードを追っていくと、 テキストパラメータとファイルパラメータの扱いの違いはここにあった。
S2MultipartRequestHandler.java
@SuppressWarnings("unchecked") @Override protected void addTextParameter(HttpServletRequest request, FileItem item) { String name = item.getFieldName(); String value = null; boolean haveValue = false; String encoding = request.getCharacterEncoding(); if (encoding != null) { try { value = item.getString(encoding); haveValue = true; } catch (Exception e) { } } if (!haveValue) { try { value = item.getString("ISO-8859-1"); } catch (java.io.UnsupportedEncodingException uee) { value = item.getString(); } haveValue = true; } if (request instanceof MultipartRequestWrapper) { MultipartRequestWrapper wrapper = (MultipartRequestWrapper) request; wrapper.setParameter(name, value); } String[] oldArray = (String[]) elementsText.get(name); String[] newArray; if (oldArray != null) { newArray = new String[oldArray.length + 1]; System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); newArray[oldArray.length] = value; } else { newArray = new String[] { value }; } elementsText.put(name, newArray); elementsAll.put(name, newArray); } @SuppressWarnings("unchecked") @Override protected void addFileParameter(FileItem item) { FormFile formFile = new S2FormFile(item); elementsFile.put(item.getFieldName(), formFile); elementsAll.put(item.getFieldName(), formFile); }
うーむ、同一のフィールド名でパラメータが送られてきた場合、 テキストパラメータは配列に格納してくれるのに対して、ファイルパラメータは、後勝ちになる模様。 (テキストパラメータは、同一のフィールド名が無くとも配列に詰め込む模様)
テキストパラメータは割と柔軟に対応できるんだねぇ・・・
次回、対策編へ!