jsf - 如何使用 JSF 2.2 上传多个文件

标签 jsf file-upload jsf-2.2

我正在尝试使用 h:inputFile 添加多个文件上传.我快速浏览了源代码,它似乎没有呈现 multiple="multiple" 的选项。 .有没有办法在不编写自定义组件的情况下解决这个问题?
如果没有,是否有建议的自定义 JSF2.2 组件可以处理多个 Ajax 文件上传?

更新:
我通过了multiple="multiple"使用 passthrough标记,但是当我调试 FileRenderer相关的代码用第二个文件覆盖第一个文件:

for (Part cur : parts) {
  if (clientId.equals(cur.getName())) {
    component.setTransient(true);
    setSubmittedValue(component, cur);
  }
}

如您所见,由于有两个 Part s 与 clientId 相同,它总是使用最后一个而不是传递一个列表。

如果有,请推荐一个替代方案。

最佳答案

How can I upload multiple files with JSF 2.2



您确实可以通过另一个 JSF 2.2 特性来实现这一点:passthrough attributes .设置 multiple 属性作为直通属性 (browser support is currently quite broad)。
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputFile ... a:multiple="true" />

但是,<h:inputFile>组件本身不支持抓取多个 Part s 来自请求并将其设置为数组或 Collection bean 属性。它只会设置与输入字段名称匹配的最后一部分。基本上,要支持多个部分,需要创建一个自定义渲染器(您应该立即捕获机会立即支持 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;
}

请注意,getter 可以用于 safety and clarity最好总是返回 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" />

该值可以绑定(bind)到 List<Part> .
private List<Part> files; // +getter+setter

关于jsf - 如何使用 JSF 2.2 上传多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16837090/

相关文章:

JavaEL : Access nested properties

java - 更改 ace 中浏览的默认按钮名称 :FileEntry

c# - HttpClient : How to upload multiple files at once

jsf - 如何将 Part 转换为 Blob,以便将其存储在 MySQL 中?

javascript - 如何将 opensocial 0.9 中的文件上传到应用程序服务器?

ajax - 来自 f :param not submitted with AJAX request when form enctype is multipart/form-data 的参数

jsf-2 - h :commandButton is not working once I wrap it in a <h:panelGroup rendered>

jsf - h :inputText changing to scientific notation

jsf - 警告 : This page calls for XML namespace http://xmlns. jcp.org/jsf/XXX 以前缀 XXX 声明,但该 namespace 不存在标签库

jsf - java.lang.NullPointerException 在 java.net.URLEncoder.encode 在 com.sun.faces.context.UrlBuilder.addValuesToParameter