JSF 2.2で複数のファイルをアップロードするにはどうすればよいですか
確かに、別の JSF 2.2 機能であるpassthrough attributesを使用してこれを実現できます。multiple
属性をパススルー属性として設定します (ブラウザのサポートは現在非常に広範です)。
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputFile ... a:multiple="true" />
ただし、コンポーネント自体は、リクエストから複数の を取得して配列またはBean プロパティとして設定することを<h:inputFile>
サポートしていません。入力フィールド名に一致する最後の部分のみを設定します。基本的に、複数のパーツをサポートするには、カスタム レンダラーを作成する必要があります (パススルー属性に頼らずに、すぐに属性をサポートする機会を利用する必要があります)。Part
Collection
multiple
ただし、レンダラー全体を作成せずに「回避策」を講じるHttpServletRequest
ために、以下の小さなユーティリティ メソッドを使用してすべてのパーツを手動で取得できます。
public static Collection<Part> getAllParts(Part part) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
return request.getParts().stream().filter(p -> part.getName().equals(p.getName())).collect(Collectors.toList());
}
したがって、以下の構成は上記のユーティリティ メソッドで動作するはずです。
<h:inputFile value="#{bean.part}" a:multiple="true" />
<h:commandButton ... action="#{bean.submit}" />
private Part file;
public void submit() throws ServletException, IOException {
for (Part part : getAllParts(file)) {
String fileName = part.getSubmittedFileName();
InputStream fileContent = part.getInputStream();
// ...
// Do your thing with it.
// E.g. https://stackoverflow.com/q/14211843/157882
}
}
public Part getFile() {
return null; // Important!
}
public void setFile(Part file) {
this.file = file;
}
安全性と明確さのために、ゲッターは常に return を返すことができることに注意してくださいnull
。実際には、getter メソッド全体が不要なはずですが、実際にはそうです。
最新のブラウザーでは、フォルダー全体を選択することもできます。これには、さらに新しいdirectory
属性のみが必要です。これは Firefox 46 以降でサポートされています (すでに 42 以降ですが、about:config で明示的に有効にする必要があります)。Webkit ベースのブラウザー (Chrome 11 以降、Safari 4 以降、および Edge) は、独自のwebkitdirectory
属性を介してこれをサポートします。したがって、両方の属性を指定すると、通常は安全です。
<h:inputFile ... a:multiple="true" a:directory="true" a:webkitdirectory="true" />
これは物理フォルダーではなく、それらのフォルダーに含まれるファイルのみを送信することに注意してください。
更新: JSF ユーティリティ ライブラリOmniFacesを使用している場合は、バージョン 2.5 以降、<o:inputFile>
複数のディレクトリの選択が面倒でなくなるはずの が提供されています。
<o:inputFile value="#{bean.files}" multiple="true" />
<o:inputFile value="#{bean.files}" directory="true" />
値は にバインドできますList<Part>
。
private List<Part> files; // +getter+setter