PrimeFaces 4.0 / JSF 2.2.x中的AJAX无法使用file upload – javax.servlet.ServletException:请求内容types不是多部分/表单数据
重要说明:此主题中讨论的问题已于2014年10月6日星期一(即将从现在开始几分钟前) 发布的PrimeFaces 5.1 final (社区版)中得到修复 。 我试图在JSF 2.2.8-02 (或API , IMPL )。
因此,如果您碰巧使用该版本( 或更高版本,无需提及 ),则甚至不需要再阅读此问题。
我有一个Web应用程序运行
- GlassFish 4.0
- 莫哈拉2.2.4
- PrimeFaces 4.0 final
除了使用AJAX上传文件以外的所有内容都很有效 以下xhtml文件通过由PrimeFaces命令button触发的AJAX请求发送多部分内容。
<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>
testing托pipebean:
@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."); } } }
从文件浏览器上载文件时,会在其侦听器中显示文件名 – fileUploadListener()
。
上传文件后,当按下给定的命令button( ajax="true"
)时,会引发以下exception。
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)
当命令button的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请求的文件,因为在PrimeFaces DataTable中使用<p:rowEditor/>
(例如每行中的图像)编辑行始终是基于AJAX的。
无论如何,我想保留GlassFish 4.0 。 我也尝试在GlassFish 4.0中降级Mojarra 2.1.9,但是它没能创build以exception结束的bundle。 GlassFish 4.0似乎不适用于低于2.2.x的Mojarra。
那么,是什么造成这个exception – PrimeFaces或JSF? 只是困惑。 在给定的环境中是否有任何解决方法来上传带有AJAX请求的文件?
编辑:
在web.xml
filter映射:
<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>
该问题与2014年1月8日发布的Mojarra版本2.2.5 (或api , impl )一起保持不变。
再次尝试2014年3月4日发布的Mojarra版本2.2.6 (或api , impl )。问题保持不变。
在2014年5月5日发布的 PrimeFaces 5.0 final上仍然不起作用。
我遇到过同样的问题。 它似乎与<p:commandButton>
比<p:fileUpload>
组件更相关,因为它可以和<h:commandButton>
(甚至可以使用ajax)。
你可以尝试:
<h:commandButton id="btnSubmit" actionListener="#{testManagedBean.insert}" value="Save"> <f:ajax execute="@all" render="@form"/> </h:commandButton>
我不能告诉你为什么或者如何运作,但它解决了我的问题。 当然不利的一面是,你必须自己去做样式,至less在Primefaces人员解决这个问题之前。
编辑 :
在挖掘源代码并进行一些debugging后,如果发现实际上有两个请求(我在<p:wizard/>
尝试过)。 第一个是实际上做file upload的multipart/form-data
。 它触发Bean中的fileUploadEvent。 我向下button的button被按下另一个formsapplication/www-urlencoded
提交。 这导致exception。 结论是,不像我在评论中写的那样压制exception是一个有效的解决scheme。 这甚至可以以不包括改变Primefaces.jar的方式来完成,如果这些人在将来的版本中解决这个问题的话,这很方便。
所以这里是需要做的事情:
- 创build一个新的类
com.yourpackage.fileupload.FileUploadRenderer
-
将以下代码复制并粘贴到新类中:
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"); } }
-
在
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>
-
你准备好了!
我们做了什么? 我们创build了自己的FileUploadRenderer,它使用isMultiPartRequest()
方法检查contentType是否真的是multipart/form-data
。 只有当这个返回true时,其余的代码才会被执行。 在其他任何情况下都不会发生这意味着不会抛出exception。 如果Primefaces修复了这个问题,您只需要从faces-config.xml
删除这些行来使用它们的类。
让我知道如果这对你有用!
编辑
这个代码检查给定的请求是否是multipart / form-datatypes。 如果不是执行被停止。 原始的Primefaces代码仍然会继续。 正如我上面提到的,如果您在Primefaces组件内上传文件,实际上有两个请求:
- 使用
<p:fileUpload/>
(enctype:multipart/form-data
)的Ajax-FileUpload - 在
<p:editRow/>
或<p:wizard/>
(enctype:application/www-form-urlencoded
)中的Ajax操作
第一个由渲染器处理,而第二个引起原始代码中的exception,因为渲染器试图处理不能处理的东西。 通过在代码中所做的更改,只有multipart/form-data
表单由渲染器处理,因此不会出现exception。 IMO显然是Primefaces的一个缺陷。 代码的差异只是private boolean isMultiPartRequest(FacesContext context)
和它在代码中的一次出现。 很高兴我能帮你!
正如Kai在他对当前问题的回答中正确地指出的那样,问题是由FileUploadRenderer
使用的NativeFileUploadDecoder
引起的,而不是检查请求是否是multipart/form-data
请求。 当组件出现在提交“常规”ajax请求的表单中时,会造成麻烦。 CommonsFileUploadDecoder
检查是否正确,这就是为什么它在没有本地file uploadparsing器的JSF 2.1中工作正常。
他用自定义渲染器解决这个问题的方法是正确的,但是这种方法相当笨拙。 在这种特殊情况下,绝对不需要复制包含200多行的全部类,只需添加几行即可。 相反,只需要扩展到这个类,然后在委托给super之前用一个if检查覆盖这个方法,如下所示:
package com.example; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import org.primefaces.component.fileupload.FileUploadRenderer; public class MyFileUploadRenderer extends FileUploadRenderer { @Override public void decode(FacesContext context, UIComponent component) { if (context.getExternalContext().getRequestContentType().toLowerCase().startsWith("multipart/")) { super.decode(context, component); } } }
就是这样(尽pipe在faces-config.xml
保留<renderer-kit>
条目)。 如果请求不是multipart
请求,则继续解码是没有意义的。 文件部分无论如何都是不可用的(当通过ExternalContext
获得相同的function时,也没有必要将其转换回javax.servlet.*
API)。
尽pipe这已经很老了,并且已经有了答案,但是我想分享一些东西,以防万一你错过了:PrimeFaces 4+现在有一个上下文参数,你可以使用它(在web.xml中)手动select应该使用哪个上传器-servlet3或commons)。 你可以使用这个来强制commons-uploader像这样:
<context-param> <param-name>primefaces.UPLOADER</param-name> <param-value>commons</param-value> </context-param>
(当然,你仍然需要FileUploadFilter,如上面和在指南中所述)。 有关更多信息,请参见PrimeFaces用户指南。
@BalusC – 您对扩展现有FileUploadRenderer
build议非常干净。 谢谢!
根据您使用的JSF版本,您可能会看到一个随机的iFramepopup。 这是一个在这里指出的错误: JAVASERVERFACES-2843
在我的第一次尝试解决这个问题(不必升级到2.2.1),我只是用CSS隐藏了iFrame。
#JSFFrameId { visibility:hidden; }
这工作,但由于某种原因,其他AJAX提交不会触发。 然后我调用了一个小脚本来删除iFrame,并解决了这个问题。
<h:commandButton id="btnSubmit" action="#{fileUploadController.upload}" value="Save" > <f:ajax execute="@all" render="frmMain" onevent="removeIFrame()" /> </h:commandButton>
JavaScript的:
function removeIFrame() { document.getElementById("JSFFrameId").removeNode(); }
我有同样的问题,在我的情况下,我已经在数据表中使用primefacesfile upload,试图修改现有的图像使用onRowEdit,这是最终与上述相同的错误。 然后我将primefaces jar更改为5.1版本。 现在它工作正常。