如何让JSF使用Apache Commons FileUpload上传文件

Tha*_*ham 5 jsf file-upload jsf-2 apache-commons-fileupload

我知道如何使用Primefaces或使用Tomahawk进行文件上传,但是,我正在尝试使用Apache Commons FileUpload进行文件上传,到目前为止,我有一些路障.即使我的表单使用multipart/form-data,当我提交表单时,内容类型也会变为application/x-www-form-urlencoded.这是我的代码

<h:body>
    <h:form enctype="multipart/form-data">
        Upload File
        <input type="file" name="file"/>
        <p:commandButton value="Submit" action="#{viewBean.submit}"/>
    </h:form>
</h:body>
Run Code Online (Sandbox Code Playgroud)

这是我的 ViewBean

@ManagedBean
@ViewScoped
public class ViewBean implements Serializable {
    public void submit() {
        String url = "/FileUploadServlet";
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            String contentType = context.getExternalContext().getRequestContentType();
            context.getExternalContext().dispatch(url);
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Exception when calling Servlet", e);
        } finally {
            context.responseComplete();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当我尝试打印上面的内容类型时,它显示出来了application/x-www-form-urlencoded.如果我把它放到ajax="false"我的p:commandButton,那么该submit()方法甚至没有被调用,但如果我取出enctype="multipart/form-data"(仍然保持ajax="false"),然后submit()被调用但它不是多部分,它是application/x-www-form-urlencoded,所以apache commons fileupload抛出异常,因为它不是多部分.似乎无论我做什么,我似乎无法获得多部分要求.请帮忙

Bal*_*usC 12

因此,当我尝试打印上面的内容类型时,它显示了application/x-www-form-urlencoded.

<p:commandButton>默认情况下,第1级的AJAX请求发送XMLHttpRequest.这并不能支持multipart/form-data.只有2级XMLHttpRequest支持它,但它只支持最新的浏览器(那些也支持HTML5),而不是在JSF JS API和PrimeFaces JS API中实现.


如果我把ajax ="false"放到我的p:commandButton中,那么甚至不会调用submit()方法

然而,这种方式multipart/form-data 被发送.不调用submit方法只是因为2.2版之前的JSF不支持multipart/form-data开箱即用的请求.默认情况下,JSF使用request.getParameter()getParameterMap()在底层HTTP servlet请求上收集提交的数据.但是,null当使用除以外的编码时,这将返回application/x-www-form-urlencoded.由于JSF根据提交的数据确定要调用的操作方法,因此当数据存在时,它将无法找到并调用它null.

理论上,如果您创建一个Filter使用Apache Commons FileUpload或新的Servlet 3.0 request.getPart()/ getParts()方法从multipart/form-data请求中提取数据并使用自定义实现包装当前HTTP Servlet请求,该实现覆盖了getParameter()所提取数据的映射的调用提供后,JSF将能够根据getParameter()呼叫结果完成所需的工作.您可以在本文中找到使用Servlet 3.0 API的具体示例,并在此答案中略微更改以利用Apache Commons FileUpload .

即将推出的JSF 2.2将有一个<h:inputFile>可绑定到Servlet 3.0 Part属性的新组件.

<h:form enctype="multipart/form-data">
    <h:inputFile value="#{bean.file}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
</h:form>
Run Code Online (Sandbox Code Playgroud)

private Part file;
Run Code Online (Sandbox Code Playgroud)

JSF 2.2最终版本计划在第一季度末发布,但目前可作为快照发布.