文件上传不适用于 PrimeFaces 4.0/JSF 2.2.x 中的 AJAX - javax.servlet.ServletException:请求内容类型不是多部分/表单数据 [英] File upload doesn't work with AJAX in PrimeFaces 4.0/JSF 2.2.x - javax.servlet.ServletException: The request content-type is not a multipart/form-data

查看:29
本文介绍了文件上传不适用于 PrimeFaces 4.0/JSF 2.2.x 中的 AJAX - javax.servlet.ServletException:请求内容类型不是多部分/表单数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

重要提示:此线程中讨论的问题是已修复PrimeFaces 5.1 最终版(社区发布)发布 2014 年 10 月 6 日星期一(几分钟前从现在开始).我尝试了 JSF 2.2.8-02(或 api, impl).

因此,如果您碰巧使用该版本(或更高,无需提及),您甚至不需要再阅读此问题.><小时>

我有一个正在运行的网络应用程序

  • 玻璃鱼 4.0
  • Mojarra 2.2.4
  • PrimeFaces 4.0 最终版

除了使用 AJAX 上传文件外,其他一切都运行良好.以下 xhtml 文件通过 PrimeFaces 命令按钮触发的 AJAX 请求发送多部分内容.

<h:头><title>测试</title></h:head><h:body><h:form prependId="true" enctype="multipart/form-data"><p:fileUpload id="txtCatImage"value="#{testManagedBean.uploadedFile}"模式=高级"dragDropSupport="true"文件限制=1"sizeLimit="100000"多个=假"allowTypes="/(.|/)(gif|jpe?g|png)$/"fileUploadListener="#{testManagedBean.fileUploadListener}"/><p:message for="txtCatImage" showSummary="false"/><p:commandButton id="btnSubmit"actionListener="#{testManagedBean.insert}"ajax="true" icon="ui-icon-check" value="保存"/></h:form></h:body>

测试托管 bean:

@ManagedBean@ViewScoped公共最终类 TestManagedBean 实现 Serializable {private static final long serialVersionUID = 1L;私人上传文件上传文件;公共 TestManagedBean(){}公共上传文件 getUploadedFile() {返回上传的文件;}public void setUploadedFile(UploadedFile uploadFile) {this.uploadedFile = UploadedFile;}public void fileUploadListener(FileUploadEvent 事件){上传文件=事件.getFile();}公共无效插入(){如果(上传文件!=空){System.out.println(uploadedFile.getFileName());}别的{System.out.println("文件对象为空.");}}}

当文件从文件浏览器上传时,它会在其侦听器中显示文件名 - fileUploadListener().

上传文件后,当按下给定的命令按钮(ajax="true")时,会导致抛出以下异常.

WARNING: javax.servlet.ServletException: The request content-type is not a multipart/form-datajavax.faces.FacesException: javax.servlet.ServletException: 请求内容类型不是多部分/表单数据在 org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:44)在 org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)在 javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)在 javax.faces.component.UIInput.decode(UIInput.java:771)在 javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)在 javax.faces.component.UIInput.processDecodes(UIInput.java:676)在 javax.faces.component.UIForm.processDecodes(UIForm.java:225)在 javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)在 javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)在 javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)在 com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)在 com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)在 com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)在 javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)在 org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)在 org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)在 filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)在 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)在 org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)在 com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)在 org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)在 org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)在 org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)在 org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)在 org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)在 org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)在 org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)在 org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)在 org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)在 java.lang.Thread.run(Thread.java:722)引起:javax.servlet.ServletException:请求内容类型不是多部分/表单数据在 org.apache.catalina.fileupload.Multipart.getPart(Multipart.java:187)在 org.apache.catalina.connector.Request.getPart(Request.java:4535)在 org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1095)在 org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)在 org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)... 48 更多严重:javax.servlet.ServletException:请求内容类型不是多部分/表单数据在 org.apache.catalina.fileupload.Multipart.getPart(Multipart.java:187)在 org.apache.catalina.connector.Request.getPart(Request.java:4535)在 org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1095)在 org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)在 org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)在 org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)在 javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)在 javax.faces.component.UIInput.decode(UIInput.java:771)在 javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)在 javax.faces.component.UIInput.processDecodes(UIInput.java:676)在 javax.faces.component.UIForm.processDecodes(UIForm.java:225)在 javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)在 javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)在 javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)在 com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)在 com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)在 com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)在 javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)在 org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)在 org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)在 filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)在 org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)在 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)在 org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)在 com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)在 org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)在 org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)在 org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)在 org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)在 org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)在 org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)在 org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)在 org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)在 org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)在 org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)在 org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)在 java.lang.Thread.run(Thread.java:722)

只有当命令按钮的ajax属性设置为false时才能工作-ajax="false".

<小时>

我已将 Tomcat 7.0.35 中的 Mojarra 版本降级到 2.1.9.它与此 Mojarra 版本以及 PrimeFaces 4.0 final(以及 PrimeFaces 4.0 RC1)一起使用 - 使用 AJAX 请求上传的文件.

我也尝试过以下 Mojarra 版本

  • 2.2.0
  • 2.2.1
  • 2.2.2
  • 2.2.3
  • 2.2.4

在 GlassFish 4.0 中,但没有一个成功通过 AJAX 请求上传文件,因为使用 <p:rowEditor/> 编辑行(以及每行中的图像,例如)在 PrimeFaces DataTable 中始终基于 AJAX.

无论如何我都想保留 GlassFish 4.0.我还尝试在 GlassFish 4.0 中降级 Mojarra 2.1.9,但未能创建以异常结尾的包.GlassFish 4.0 似乎不适用于低于 2.2.x 的 Mojarra.

那么,是什么导致了这个异常——PrimeFaces 还是 JSF?只是糊涂了.在此给定环境中,是否有任何解决方法可以使用 AJAX 请求上传文件?

<小时>

web.xml 中的过滤器映射:

<filter-name>PrimeFaces 文件上传过滤器</filter-name><filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class></过滤器><过滤器映射><filter-name>PrimeFaces 文件上传过滤器</filter-name><servlet-name>Faces Servlet</servlet-name></过滤器映射><小服务程序><servlet-name>Faces Servlet</servlet-name><servlet-class>javax.faces.webapp.FacesServlet</servlet-class><启动时加载>1</启动时加载></servlet><servlet-mapping><servlet-name>Faces Servlet</servlet-name><url-pattern>*.jsf</url-pattern></servlet-mapping>

<小时>

问题随着 Mojarra 版本2.2.5(或 api, impl) 于 2014 年 1 月 8 日发布.

<小时>

再次尝试 Mojarra 版本 2.2.6(或 api,impl) 于2014年3月4日发布.问题依旧.

<小时>

仍然不适用于 PrimeFaces 5.0 final 于 2014 年 5 月 5 日发布.

解决方案

我遇到了同样的问题.与 组件相比,它似乎与 <p:commandButton> 更相关,因为它与 (即使使用 ajax).

你可以试试:

<f:ajax execute="@all" render="@form"/></h:commandButton>

我不能告诉你它为什么或如何工作,但它为我解决了这个问题.缺点当然是,你必须自己做造型,至少直到Primefaces 人员解决了这个问题.

编辑:

在挖掘源代码并进行一些调试之后,如果发现实际上有两个请求(我在 <p:wizard/> 中尝试过).第一个是 multipart/form-data 一个实际执行文件上传的.它触发 Bean 中的 fileUploadEvent.我按下了向导 next 按钮,提交了另一个带有 enctype application/www-urlencoded 的表单.这会导致异常.结论是,与我在抑制异常的评论中所写的不同,这是一个有效的解决方案.这甚至可以通过不包括更改 Primefaces.jar 的方式来完成,如果这些人在未来版本中解决问题,这很方便.

所以这里是需要做的:

  • 创建一个新类com.yourpackage.fileupload.FileUploadRenderer
  • 将以下代码复制并粘贴到您的新类中:

    package com.yourpackage.fileupload.fileupload;导入 java.io.IOException;导入 javax.faces.FacesException;导入 javax.faces.component.UIComponent;导入 javax.faces.context.FacesContext;导入 javax.faces.context.ResponseWriter;导入 javax.servlet.http.HttpServletRequest;导入 org.primefaces.component.fileupload.C​​ommonsFileUploadDecoder;导入 org.primefaces.component.fileupload.FileUpload;导入 org.primefaces.component.fileupload.NativeFileUploadDecoder;导入 org.primefaces.config.ConfigContainer;导入 org.primefaces.context.RequestContext;导入 org.primefaces.expression.SearchExpressionFacade;导入 org.primefaces.renderkit.CoreRenderer;导入 org.primefaces.util.HTML;导入 org.primefaces.util.WidgetBuilder;公共类 FileUploadRenderer 扩展 CoreRenderer {@覆盖公共无效解码(FacesContext 上下文,UIComponent 组件){FileUpload fileUpload = (FileUpload) 组件;如果 (!fileUpload.isDisabled()) {ConfigContainer cc = RequestContext.getCurrentInstance().getApplicationContext().getConfig();字符串上传者 = cc.getUploader();布尔值 isAtLeastJSF22 = cc.isAtLeastJSF22();如果(上传者.等于(自动")){如果(isAtLeastJSF22){如果(isMultiPartRequest(上下文)){NativeFileUploadDecoder.decode(context, fileUpload);}} 别的 {CommonsFileUploadDecoder.decode(context, fileUpload);}} else if (uploader.equals("native")) {如果(!isAtLeastJSF22){throw new FacesException("本机上传器至少需要一个 JSF 2.2 运行时");}NativeFileUploadDecoder.decode(context, fileUpload);} else if (uploader.equals("commons")) {CommonsFileUploadDecoder.decode(context, fileUpload);}}}@覆盖public void encodeEnd(FacesContext context, UIComponent component) 抛出 IOException {FileUpload fileUpload = (FileUpload) 组件;编码标记(上下文,文件上传);if (fileUpload.getMode().equals("advanced")) {编码脚本(上下文,文件上传);}}protected void encodeScript(FacesContext context, FileUpload fileUpload) 抛出 IOException {String clientId = fileUpload.getClientId(context);String update = fileUpload.getUpdate();String process = fileUpload.getProcess();WidgetBuilder wb = getWidgetBuilder(context);wb.initWithDomReady("FileUpload", fileUpload.resolveWidgetVar(), clientId, "fileupload");wb.attr("auto", fileUpload.isAuto(), false).attr("dnd", fileUpload.isDragDropSupport(), true).attr("update", SearchExpressionFacade.resolveComponentsForClient(context, fileUpload, update), null).attr("process", SearchExpressionFacade.resolveComponentsForClient(context, fileUpload, process), null).attr("maxFileSize", fileUpload.getSizeLimit(), Long.MAX_VALUE).attr("fileLimit", fileUpload.getFileLimit(), Integer.MAX_VALUE).attr("invalidFileMessage", fileUpload.getInvalidFileMessage(), null).attr("invalidSizeMessage", fileUpload.getInvalidSizeMessage(), null).attr("fileLimitMessage", fileUpload.getFileLimitMessage(), null).attr("messageTemplate", fileUpload.getMessageTemplate(), null).attr("previewWidth", fileUpload.getPreviewWidth(), 80).attr("disabled", fileUpload.isDisabled(), false).callback("onstart", "function()", fileUpload.getOnstart()).callback("onerror", "function()", fileUpload.getOnerror()).callback("oncomplete", "function()", fileUpload.getOncomplete());如果 (fileUpload.getAllowTypes() != null) {wb.append(",allowTypes:").append(fileUpload.getAllowTypes());}wb.finish();}protected void encodeMarkup(FacesContext context, FileUpload fileUpload) 抛出 IOException {if (fileUpload.getMode().equals("simple")) {encodeSimpleMarkup(上下文,文件上传);} 别的 {encodeAdvancedMarkup(上下文,文件上传);}}protected void encodeAdvancedMarkup(FacesContext context, FileUpload fileUpload) 抛出 IOException {ResponseWriter writer = context.getResponseWriter();String clientId = fileUpload.getClientId(context);字符串样式 = fileUpload.getStyle();String styleClass = fileUpload.getStyleClass();styleClass = styleClass == null ?FileUpload.C​​ONTAINER_CLASS : FileUpload.C​​ONTAINER_CLASS + " " + styleClass;boolean disabled = fileUpload.isDisabled();writer.startElement("div", fileUpload);writer.writeAttribute("id", clientId, "id");writer.writeAttribute("class", styleClass, styleClass);如果(样式!= null){writer.writeAttribute("style", style, "style");}//按钮栏writer.startElement("div", fileUpload);writer.writeAttribute("class", FileUpload.BUTTON_BAR_CLASS, null);//选择按钮编码选择按钮(上下文,文件上传,禁用);如果 (!fileUpload.isAuto()) {encodeButton(context, fileUpload.getUploadLabel(), FileUpload.UPLOAD_BUTTON_CLASS, "ui-icon-arrowreturnthick-1-n");encodeButton(context, fileUpload.getCancelLabel(), FileUpload.C​​ANCEL_BUTTON_CLASS, "ui-icon-cancel");}writer.endElement("div");//内容writer.startElement("div", null);writer.writeAttribute("class", FileUpload.C​​ONTENT_CLASS, null);writer.startElement("table", null);writer.writeAttribute("class", FileUpload.FILES_CLASS, null);writer.startElement("tbody", null);writer.endElement("tbody");writer.endElement("table");writer.endElement("div");writer.endElement("div");}protected void encodeSimpleMarkup(FacesContext context, FileUpload fileUpload) 抛出 IOException {encodeInputField(context, fileUpload, fileUpload.getClientId(context));}protected void encodeChooseButton(FacesContext context, FileUpload fileUpload, boolean disabled) 抛出 IOException {ResponseWriter writer = context.getResponseWriter();String clientId = fileUpload.getClientId(context);String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " " + FileUpload.C​​HOOSE_BUTTON_CLASS;如果(禁用){cssClass += " ui-state-disabled";}writer.startElement("span", null);writer.writeAttribute("class", cssClass, null);//按钮图标writer.startElement("span", null);writer.writeAttribute("class", HTML.BUTTON_LEFT_ICON_CLASS + " ui-icon-plusthick", null);writer.endElement("span");//文本writer.startElement("span", null);writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);writer.writeText(fileUpload.getLabel(), "value");writer.endElement("span");如果(!禁用){encodeInputField(context, fileUpload, clientId + "_input");}writer.endElement("span");}protected void encodeInputField(FacesContext context, FileUpload fileUpload, String clientId) 抛出 IOException {ResponseWriter writer = context.getResponseWriter();writer.startElement("输入", null);writer.writeAttribute("type", "file", null);writer.writeAttribute("id", clientId, null);writer.writeAttribute("name", clientId, null);如果 (fileUpload.isMultiple()) {writer.writeAttribute("multiple", "multiple", null);}如果 (fileUpload.getStyle() != null) {writer.writeAttribute("style", fileUpload.getStyle(), "style");}如果 (fileUpload.getStyleClass() != null) {writer.writeAttribute("class", fileUpload.getStyleClass(), "styleClass");}如果 (fileUpload.isDisabled()) {writer.writeAttribute("disabled", "disabled", "disabled");}writer.endElement("输入");}protected void encodeButton(FacesContext context, String label, String styleClass, String icon) 抛出 IOException {ResponseWriter writer = context.getResponseWriter();String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " ui-state-disabled " + styleClass;writer.startElement("button", null);writer.writeAttribute("type", "button", null);writer.writeAttribute("class", cssClass, null);writer.writeAttribute("disabled", "disabled", null);//按钮图标String iconClass = HTML.BUTTON_LEFT_ICON_CLASS;writer.startElement("span", null);writer.writeAttribute("class", iconClass + " " + icon, null);writer.endElement("span");//文本writer.startElement("span", null);writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);writer.writeText(label, "value");writer.endElement("span");writer.endElement("按钮");}私有布尔值 isMultiPartRequest(FacesContext 上下文) {如果(上下文==空){返回假;}return ((HttpServletRequest) context.getExternalContext().getRequest()).getContentType().startsWith("multipart");}}

  • 在您的 faces-config.xml 底部添加以下几行:

    <渲染器><component-family>org.primefaces.component</component-family><renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type><renderer-class>com.yourpackage.fileupload.FileUploadRenderer</renderer-class></渲染器></render-kit>

  • 你准备好了!

我们做了什么?我们创建了自己的 FileUploadRenderer,它使用 isMultiPartRequest() 方法检查 contentType 是否真的是 multipart/form-data.只有当这返回 true 时,才会执行其余的代码.在任何其他情况下都不会发生任何事情,这意味着不会抛出异常.如果 Primefaces 修复了这个问题,您只需要从 faces-config.xml 中删除这些行即可使用它们的类.

告诉我这是否适合您!

编辑

此代码检查给定的请求是否为 multipart/form-data 类型.如果不是,则停止执行.无论如何,原始的 Primefaces 代码将继续.正如我上面提到的,如果您在 Primefaces 组件中上传文件,实际上会发出两个请求:

  1. 使用(enctype:multipart/form-data)
  2. 的Ajax-FileUpload
  3. 中的 Ajax 操作(编码类型:application/www-form-urlencoded)

第一个由渲染器处理,而第二个导致原始代码中的异常,因为渲染器试图处理它无法处理的事情.随着代码中的更改,渲染器仅处理 multipart/form-data 表单,因此不会发生异常.IMO 这显然是 Primefaces 来源中的一个错误.代码差异仅在于方法 private boolean isMultiPartRequest(FacesContext context) 及其在代码中的一次出现.很高兴能帮到你!

Important : The issue which is discussed in this thread has been fixed as of PrimeFaces 5.1 final (community release) released on Monday, October 6, 2014 (just a few minutes ago from now). I attempted on JSF 2.2.8-02 (or api, impl).

As such, if you happened to use that version (or higher, no need to mention), you would not even need to read this question anymore.


I have a web application running on

  • GlassFish 4.0
  • Mojarra 2.2.4
  • PrimeFaces 4.0 final

Everything except file upload with AJAX works well. The following xhtml file sends multipart contents via an AJAX request triggered by a PrimeFaces command button.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:p="http://primefaces.org/ui"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Test</title>
    </h:head>
    <h:body>
        <h:form prependId="true" enctype="multipart/form-data">
            <p:fileUpload id="txtCatImage"
                          value="#{testManagedBean.uploadedFile}"
                          mode="advanced"
                          dragDropSupport="true"
                          fileLimit="1"
                          sizeLimit="100000"
                          multiple="false"
                          allowTypes="/(.|/)(gif|jpe?g|png)$/"
                          fileUploadListener="#{testManagedBean.fileUploadListener}"/>

            <p:message for="txtCatImage" showSummary="false"/>
            <p:commandButton id="btnSubmit" 
                             actionListener="#{testManagedBean.insert}" 
                             ajax="true" icon="ui-icon-check" value="Save"/>                
        </h:form>
    </h:body>
</html>

The test managed bean:

@ManagedBean
@ViewScoped
public final class TestManagedBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private UploadedFile uploadedFile;

    public TestManagedBean(){}

    public UploadedFile getUploadedFile() {
        return uploadedFile;
    }

    public void setUploadedFile(UploadedFile uploadedFile) {
        this.uploadedFile = uploadedFile;
    }

    public void fileUploadListener(FileUploadEvent event){
        uploadedFile=event.getFile();
    }

    public void insert(){
        if(uploadedFile!=null){
            System.out.println(uploadedFile.getFileName());
        }
        else{
            System.out.println("The file object is null.");
        }
    }
}

When a file is uploaded from a file browser, it shows the file name in its listener - fileUploadListener().

After uploading a file, when the given command button is pressed (ajax="true"), it causes the following exception to be thrown.

WARNING:   javax.servlet.ServletException: The request content-type is not a multipart/form-data
javax.faces.FacesException: javax.servlet.ServletException: The request content-type is not a multipart/form-data
    at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:44)
    at org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)
    at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)
    at javax.faces.component.UIInput.decode(UIInput.java:771)
    at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)
    at javax.faces.component.UIInput.processDecodes(UIInput.java:676)
    at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
    at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
    at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
    at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)
    at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.servlet.ServletException: The request content-type is not a multipart/form-data
    at org.apache.catalina.fileupload.Multipart.getPart(Multipart.java:187)
    at org.apache.catalina.connector.Request.getPart(Request.java:4535)
    at org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1095)
    at org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)
    at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)
    ... 48 more

SEVERE:   javax.servlet.ServletException: The request content-type is not a multipart/form-data
    at org.apache.catalina.fileupload.Multipart.getPart(Multipart.java:187)
    at org.apache.catalina.connector.Request.getPart(Request.java:4535)
    at org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1095)
    at org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)
    at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)
    at org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)
    at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)
    at javax.faces.component.UIInput.decode(UIInput.java:771)
    at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)
    at javax.faces.component.UIInput.processDecodes(UIInput.java:676)
    at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
    at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
    at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
    at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)
    at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:722)

It can only work, when the ajax attribute of the command button is set to false - ajax="false".


I have downgraded the Mojarra version to 2.1.9 in Tomcat 7.0.35. It worked with this Mojarra version along with PrimeFaces 4.0 final (and PrimeFaces 4.0 RC1 too) - files uploaded with an AJAX request.

I have alternatively tried on the following Mojarra versions

  • 2.2.0
  • 2.2.1
  • 2.2.2
  • 2.2.3
  • 2.2.4

in GlassFish 4.0 but none of them succeeded to upload files with an AJAX request which is highly required because editing of rows using <p:rowEditor/> (along with images in each row, for example) in PrimeFaces DataTable is always AJAX based.

I want to keep GlassFish 4.0 anyhow. I have also tried to downgrade Mojarra 2.1.9 in GlassFish 4.0 but it failed to create bundles ending with an exception. GlassFish 4.0 doesn't seem to work with Mojarra lower than 2.2.x.

So, what is responsible for causing this exception - PrimeFaces or JSF? Just confused. Is there any workaround to upload files with AJAX requests in this given environment?


EDIT:

Filter mapping in web.xml:

<filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>


The problem remains stationary along with the Mojarra version 2.2.5 (or api, impl) released on January 08, 2014.


Once again tried on the Mojarra version 2.2.6 (or api, impl) released on March 04, 2014. The problem remains intact.


Still does not work on PrimeFaces 5.0 final released on May 05, 2014.

解决方案

I had the same issue. It seems to be more related to the <p:commandButton> than the <p:fileUpload> component, since it works with an <h:commandButton> (even with ajax).

You could try:

<h:commandButton id="btnSubmit" actionListener="#{testManagedBean.insert}" value="Save">
    <f:ajax execute="@all" render="@form"/>
</h:commandButton> 

I cannot tell you why or how it works, but it fixed the issue for me. The downside of course is, that you have to do the styling by yourself, at least until the Primefaces guys fix this issue.

EDIT:

After digging in the sources and doing some debugging if figured out that there are actually two requests made (I tried in <p:wizard/>). The first one is the multipart/form-data one which actually does the file upload. It fires the fileUploadEvent in the Bean. I the wizards next button is pressed another form with enctype application/www-urlencoded is submitted. This causes the exception. Conclusion is, that unlike what I wrote in the comment suppressing the exception is a valid solution. This can even be done in a way that does not include changing the Primefaces.jar which is handy if the guys fix the issue in a future version.

So here is what needs to be done:

  • Create a new class com.yourpackage.fileupload.FileUploadRenderer
  • Copy and paste the following code inside your new class:

    package com.yourpackage.fileupload.fileupload;
    
    import java.io.IOException;
    
    import javax.faces.FacesException;
    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    import javax.faces.context.ResponseWriter;
    import javax.servlet.http.HttpServletRequest;
    
    import org.primefaces.component.fileupload.CommonsFileUploadDecoder;
    import org.primefaces.component.fileupload.FileUpload;
    import org.primefaces.component.fileupload.NativeFileUploadDecoder;
    import org.primefaces.config.ConfigContainer;
    import org.primefaces.context.RequestContext;
    import org.primefaces.expression.SearchExpressionFacade;
    import org.primefaces.renderkit.CoreRenderer;
    import org.primefaces.util.HTML;        
    import org.primefaces.util.WidgetBuilder;
    
    public class FileUploadRenderer extends CoreRenderer {
    
        @Override
        public void decode(FacesContext context, UIComponent component) {
            FileUpload fileUpload = (FileUpload) component;
    
            if (!fileUpload.isDisabled()) {
                ConfigContainer cc = RequestContext.getCurrentInstance().getApplicationContext().getConfig();
                String uploader = cc.getUploader();
                boolean isAtLeastJSF22 = cc.isAtLeastJSF22();
    
                if (uploader.equals("auto")) {
                    if (isAtLeastJSF22) {
                        if (isMultiPartRequest(context)) {
                            NativeFileUploadDecoder.decode(context, fileUpload);
                        }
                    } else {
                        CommonsFileUploadDecoder.decode(context, fileUpload);
                    }
                } else if (uploader.equals("native")) {
                    if (!isAtLeastJSF22) {
                        throw new FacesException("native uploader requires at least a JSF 2.2 runtime");
                    }
    
                    NativeFileUploadDecoder.decode(context, fileUpload);
                } else if (uploader.equals("commons")) {
                    CommonsFileUploadDecoder.decode(context, fileUpload);
                }
            }
        }
    
        @Override
        public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
            FileUpload fileUpload = (FileUpload) component;
    
            encodeMarkup(context, fileUpload);
    
            if (fileUpload.getMode().equals("advanced")) {
                encodeScript(context, fileUpload);
            }
        }
    
        protected void encodeScript(FacesContext context, FileUpload fileUpload) throws IOException {
            String clientId = fileUpload.getClientId(context);
            String update = fileUpload.getUpdate();
            String process = fileUpload.getProcess();
            WidgetBuilder wb = getWidgetBuilder(context);
            wb.initWithDomReady("FileUpload", fileUpload.resolveWidgetVar(), clientId, "fileupload");
    
            wb.attr("auto", fileUpload.isAuto(), false)
                    .attr("dnd", fileUpload.isDragDropSupport(), true)
                    .attr("update", SearchExpressionFacade.resolveComponentsForClient(context, fileUpload, update), null)
                    .attr("process", SearchExpressionFacade.resolveComponentsForClient(context, fileUpload, process), null)
                    .attr("maxFileSize", fileUpload.getSizeLimit(), Long.MAX_VALUE)
                    .attr("fileLimit", fileUpload.getFileLimit(), Integer.MAX_VALUE)
                    .attr("invalidFileMessage", fileUpload.getInvalidFileMessage(), null)
                    .attr("invalidSizeMessage", fileUpload.getInvalidSizeMessage(), null)
                    .attr("fileLimitMessage", fileUpload.getFileLimitMessage(), null)
                    .attr("messageTemplate", fileUpload.getMessageTemplate(), null)
                    .attr("previewWidth", fileUpload.getPreviewWidth(), 80)
                    .attr("disabled", fileUpload.isDisabled(), false)
                    .callback("onstart", "function()", fileUpload.getOnstart())
                    .callback("onerror", "function()", fileUpload.getOnerror())
                    .callback("oncomplete", "function()", fileUpload.getOncomplete());
    
            if (fileUpload.getAllowTypes() != null) {
                wb.append(",allowTypes:").append(fileUpload.getAllowTypes());
            }
    
            wb.finish();
        }
    
        protected void encodeMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
            if (fileUpload.getMode().equals("simple")) {
                encodeSimpleMarkup(context, fileUpload);
            } else {
                encodeAdvancedMarkup(context, fileUpload);
            }
        }
    
        protected void encodeAdvancedMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
            ResponseWriter writer = context.getResponseWriter();
            String clientId = fileUpload.getClientId(context);
            String style = fileUpload.getStyle();
            String styleClass = fileUpload.getStyleClass();
            styleClass = styleClass == null ? FileUpload.CONTAINER_CLASS : FileUpload.CONTAINER_CLASS + " " + styleClass;
            boolean disabled = fileUpload.isDisabled();
    
            writer.startElement("div", fileUpload);
            writer.writeAttribute("id", clientId, "id");
            writer.writeAttribute("class", styleClass, styleClass);
            if (style != null) {
                writer.writeAttribute("style", style, "style");
            }
    
            //buttonbar
            writer.startElement("div", fileUpload);
            writer.writeAttribute("class", FileUpload.BUTTON_BAR_CLASS, null);
    
            //choose button
            encodeChooseButton(context, fileUpload, disabled);
    
            if (!fileUpload.isAuto()) {
                encodeButton(context, fileUpload.getUploadLabel(), FileUpload.UPLOAD_BUTTON_CLASS, "ui-icon-arrowreturnthick-1-n");
                encodeButton(context, fileUpload.getCancelLabel(), FileUpload.CANCEL_BUTTON_CLASS, "ui-icon-cancel");
            }
    
            writer.endElement("div");
    
            //content
            writer.startElement("div", null);
            writer.writeAttribute("class", FileUpload.CONTENT_CLASS, null);
    
            writer.startElement("table", null);
            writer.writeAttribute("class", FileUpload.FILES_CLASS, null);
            writer.startElement("tbody", null);
            writer.endElement("tbody");
            writer.endElement("table");
    
            writer.endElement("div");
    
            writer.endElement("div");
        }
    
        protected void encodeSimpleMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
            encodeInputField(context, fileUpload, fileUpload.getClientId(context));
        }
    
        protected void encodeChooseButton(FacesContext context, FileUpload fileUpload, boolean disabled) throws IOException {
            ResponseWriter writer = context.getResponseWriter();
            String clientId = fileUpload.getClientId(context);
            String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " " + FileUpload.CHOOSE_BUTTON_CLASS;
            if (disabled) {
                cssClass += " ui-state-disabled";
            }
    
            writer.startElement("span", null);
            writer.writeAttribute("class", cssClass, null);
    
            //button icon 
            writer.startElement("span", null);
            writer.writeAttribute("class", HTML.BUTTON_LEFT_ICON_CLASS + " ui-icon-plusthick", null);
            writer.endElement("span");
    
            //text
            writer.startElement("span", null);
            writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
            writer.writeText(fileUpload.getLabel(), "value");
            writer.endElement("span");
    
            if (!disabled) {
                encodeInputField(context, fileUpload, clientId + "_input");
            }
    
            writer.endElement("span");
        }
    
        protected void encodeInputField(FacesContext context, FileUpload fileUpload, String clientId) throws IOException {
            ResponseWriter writer = context.getResponseWriter();
    
            writer.startElement("input", null);
            writer.writeAttribute("type", "file", null);
            writer.writeAttribute("id", clientId, null);
            writer.writeAttribute("name", clientId, null);
    
            if (fileUpload.isMultiple()) {
                writer.writeAttribute("multiple", "multiple", null);
            }
            if (fileUpload.getStyle() != null) {
                writer.writeAttribute("style", fileUpload.getStyle(), "style");
            }
            if (fileUpload.getStyleClass() != null) {
                writer.writeAttribute("class", fileUpload.getStyleClass(), "styleClass");
            }
            if (fileUpload.isDisabled()) {
                writer.writeAttribute("disabled", "disabled", "disabled");
            }
    
            writer.endElement("input");
        }
    
        protected void encodeButton(FacesContext context, String label, String styleClass, String icon) throws IOException {
            ResponseWriter writer = context.getResponseWriter();
            String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " ui-state-disabled " + styleClass;
    
            writer.startElement("button", null);
            writer.writeAttribute("type", "button", null);
            writer.writeAttribute("class", cssClass, null);
            writer.writeAttribute("disabled", "disabled", null);
    
            //button icon
            String iconClass = HTML.BUTTON_LEFT_ICON_CLASS;
            writer.startElement("span", null);
            writer.writeAttribute("class", iconClass + " " + icon, null);
            writer.endElement("span");
    
            //text
            writer.startElement("span", null);
            writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
            writer.writeText(label, "value");
            writer.endElement("span");
            writer.endElement("button");
        }
    
        private boolean isMultiPartRequest(FacesContext context) {
            if (context == null) {
                return false;
            }
    
            return ((HttpServletRequest) context.getExternalContext().getRequest()).getContentType().startsWith("multipart");
        }
    }
    

  • Add the following lines at the bottom of your faces-config.xml:

    <render-kit>
        <renderer>
            <component-family>org.primefaces.component</component-family>
            <renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type>
            <renderer-class>com.yourpackage.fileupload.FileUploadRenderer</renderer-class>
        </renderer>
    </render-kit>
    

  • You're ready to go!

What have we done? We created our own FileUploadRenderer which checks if the contentType is really multipart/form-data using the method isMultiPartRequest(). Only if this returns true the rest of the code is executed. In any other case nothing will happen which means that no exception will be thrown. If Primefaces fixes this issue you just need to remove the lines from your faces-config.xml to use their class.

Let me know if that works for you!

EDIT

This code checks wether or not the given request is of type multipart/form-data. If it is not the execution is stopped. The original Primefaces code would continue anyway. As I mentioned above if you upload a file inside a Primefaces component there are actually two requests made:

  1. The Ajax-FileUpload using the <p:fileUpload/> (enctype: multipart/form-data)
  2. The Ajax action in the <p:editRow/> or <p:wizard/> (enctype: application/www-form-urlencoded)

The first one is handled by the renderer while the second one causes the exception in the original code since the renderer tries to handle something which it is not capable of. With the changes made in the code only multipart/form-data forms are handled by the renderer so no exceptions occur. IMO it is clearly a bug in the sources of Primefaces. The code differences is just the method private boolean isMultiPartRequest(FacesContext context) and its one occurrence in the code. Glad I could help you!

这篇关于文件上传不适用于 PrimeFaces 4.0/JSF 2.2.x 中的 AJAX - javax.servlet.ServletException:请求内容类型不是多部分/表单数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆