5

我知道如何使用 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>

这是我的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();
        }
    }
}

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

4

1 回答 1

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 发送一个完全值得的。不调用提交方法只是因为 2.2 版之前的 JSF 不支持multipart/form-data开箱即用的请求。request.getParameter()JSF 默认使用底层getParameterMap()HTTP servlet 请求收集提交的数据。null但是,当使用非编码时,这将返回application/x-www-form-urlencoded。由于 JSF 是根据提交的数据来确定要调用的 action 方法,所以当数据为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.0Part属性的新组件。

<h:form enctype="multipart/form-data">
    <h:inputFile value="#{bean.file}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
</h:form>

private Part file;

JSF 2.2 最终版本计划在第一季度末发布,但目前以快照版本的形式提供。

于 2012-02-07T12:32:27.940 回答