JSF 2.2 - 文件上传不适用于 Ajax。表单的编码类型似乎不正确(仅通过 AJAX)

Posted

技术标签:

【中文标题】JSF 2.2 - 文件上传不适用于 Ajax。表单的编码类型似乎不正确(仅通过 AJAX)【英文标题】:JSF 2.2 - fileupload does not work with Ajax. Form appears to have incorrect enctype (only via AJAX) 【发布时间】:2013-04-26 13:14:22 【问题描述】:

尝试实现 JSF 2.2 示例我有以下代码:

<h:form prependId="false" enctype="multipart/form-data">

    <!-- Now it's the AJAX file upload component -->
    <h:inputFile id="fileUpload" value="#someBean.file" >
        <f:ajax />
    </h:inputFile>

    <h:commandButton value="Upload" />
</h:form>

根据一些 JSF 2.2 这应该可以工作,但在我的情况下它给了我以下错误:

请求不包含 multipart/form-data 或 multipart/mixed 流,内容类型标头是 应用程序/x-www-form-urlencoded;charset=UTF-8

查看请求虽然我已正确设置表单编码类型,但部分请求已提交:

内容类型:application/x-www-form-urlencoded;charset=UTF-8 Faces-Request:partial/ajax

注意,web.xml 也被修改为:

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <multipart-config>
        <location>c:\dotmp</location>
        <max-file-size>20848820</max-file-size>
        <max-request-size>418018841</max-request-size>
        <file-size-threshold>1048576</file-size-threshold>
    </multipart-config>
</servlet>

我使用的是 Mojarra 2.2.0-m15,但也尝试过使用早期版本。有谁知道有关此问题的任何有用信息,我认为这是一个错误?

【问题讨论】:

【参考方案1】:

我不确定发生了什么,因为我以前从未见过。当使用今天的 Mojarra 2.2.1 快照时,以下构造适用于我,您可以从 What's new in JSF 2.2? 中提到的“implementation jar”链接下载该快照

<h:form enctype="multipart/form-data">
    <h:inputFile value="#bean.file" required="true">
        <f:ajax listener="#bean.handleFileUpload" render="@form" />
    </h:inputFile>
    <h:messages />
</h:form>

private Part file;

public void handleFileUpload(AjaxBehaviorEvent event) 
    System.out.println("file size: " + file.getSize());
    System.out.println("file type: " + file.getContentType());
    System.out.println("file info: " + file.getHeader("Content-Disposition"));


// ...

我建议尝试较新的 Mojarra 版本。显然,在较旧的 Mojarra 版本中存在一个错误,该错误无法使用 &lt;iframe&gt; hack 创建正确的 multipart/form-data 请求,最终导致此错误。 mXX 版本无论如何都是 beta 版本,不应依赖于生产。这个错误理论上也可能是特定于浏览器的,但它目前在 Chrome 26、Firefox 20 和 IE 10 中对我来说可以正常工作。

我看到的唯一问题是隐藏的&lt;iframe&gt; 在 Chrome 和 Firefox 中仍然可见,如下所示:

似乎他们忘记在生成的&lt;iframe&gt; 中将frameborder 属性设置为0。我已经报告了issue 2861。

【讨论】:

感谢 BalusC 的回复。我对 JSF2.2 很恼火,所以切换回最新版本的 JSF2.1 并使用您的 Omnifaces 渲染工具包用于 html5。对于 filwdownload,我从 balusc.blogspot.co.uk/2009/12/… 遵循了您的教程,令人惊讶的是,我得到了完全相同的错误。原因:org.apache.tomcat.util.http.fileupload.FileUploadBase$InvalidContentTypeException:请求不包含 multipart/form-data 或 multipart/mixed 流,内容类型标头为 application/x-www-form-urlencoded ;charset=UTF-8 也许您正在嵌套表单?如果您曾经试图将问题隔离为一个完全值得的 SSCCE,那将是一个相当明显的错误。 希望我有那么幸运。我上面的内容是在它自己的页面上以及您的示例中的代码。这只是一种形式,只有在我使用 Ajax 提交时才会发生,否则它可以正常工作。 我博客中的 JSF 2.0 文件上传组件与 f:ajax 不兼容。 JSF 2.2 内置的文件上传组件是。 我试过你提供的罐子,效果很好。据我所知,javascript没有考虑表单类型,而是为表单类型做出了自己的决定。你知道有最新 jsf2.2.1-SNAPSHOT 的 maven 仓库吗?【参考方案2】:

我修复了 JSF(和其他部分)的 JavaScript,以在 servlet 标准 2 上启用带和不带 AJAX 的多部分请求。

JSF 2.2 文件上传从 servlet 版本 3 开始工作。此外,称为“IFrame Transport”的负责传输层未处于发布状态。所以我添加了一个透明的Multipart请求,完成了传输层并将所有内容放在一起上传标签:

<e:inputFile id="file" value="#fileUpload.file" filename="#fileUpload.filename"
    mimeType="#fileUpload.mimeType"/>

标签与 AJAX、传统页面提交和 servlet 标准 2 / 3 一起使用。不是最好的实现,但它的工作几乎是透明的。该解决方案可通过http://www.intersult.com/wiki/page/JSF%20Ext#section-JSF+Ext-FileUpload 访问(请使用翻译)。

欢迎评论。

【讨论】:

你向 JSF 的人报告过吗? 我在几周前提出了一个相关的错误,但仍在等待中。见:java.net/jira/browse/JAVASERVERFACES-2871【参考方案3】:

我在 PrimeFaces &lt;p:fileUpload mode="simple" 使用 javax.faces-2.2.6.jar 时遇到了同样的问题。当我从 &lt;h:commandButton 禁用 ajax 时,问题消失了。在我的情况下,刷新整个页面是可以的。

【讨论】:

以上是关于JSF 2.2 - 文件上传不适用于 Ajax。表单的编码类型似乎不正确(仅通过 AJAX)的主要内容,如果未能解决你的问题,请参考以下文章

JSF 2.2 h:inputFile 不适用于漂亮的面孔[重复]

JSF 2.2 webapp适用于本地计算机,但不适用于服务器

jsf 2.2(最终版)不适用于 Jboss 7.1.1

Spring Security 3.1.4 taglib 授权/身份验证不适用于 Tomcat 7 上 JSF 2.2 中的角色层次结构

JQuery AJAX 上传文件不适用于超过 10 MB 的文件

文件上传正在使用 Postman,但不适用于从浏览器运行的 Javascript