文件上传不适用于PrimeFaces 4.0/JSF 2.2.x中的AJAX - javax.servlet.ServletException:请求内容类型不是multipart/form-data

Tin*_*iny 28 jsf primefaces jsf-2.2 glassfish-4

重要提示:此线程中讨论的问题已于2014年10月6日星期一(几分钟前)发布PrimeFaces 5.1 final(社区发布)中得到修复.我尝试了JSF 2.2.8-02(或api,impl).

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


我正在运行一个Web应用程序

  • GlassFish 4.0
  • Mojarra 2.2.4
  • PrimeFaces 4.0决赛

除了使用AJAX上传文件外,其他一切都运行良好.以下xhtml文件通过PrimeFaces命令按钮触发的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>
Run Code Online (Sandbox Code Playgroud)

测试托管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.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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)
Run Code Online (Sandbox Code Playgroud)

只有当命令按钮的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,但它无法创建以异常结尾的bundle.GlassFish 4.0似乎不适用于低于2.2.x的Mojarra.

那么,造成这种异常的原因是什么 - PrimeFaces还是JSF?只是困惑.在这个给定的环境中,是否有任何解决方法可以上传带有AJAX请求的文件?


编辑:

过滤映射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>
Run Code Online (Sandbox Code Playgroud)

随着2014年1月8日发布的Mojarra 2.2.5版(或api,impl)问题,该问题仍然存在.


再次尝试2014年3月4日发布的Mojarra 2.2.6版(或api,impl).问题依然存在.


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

Bal*_*usC 51

正如Kai在对当前问题的回答中正确地指出的那样,问题是NativeFileUploadDecoderFileUploadRenderer不检查请求是否是multipart/form-data请求而使用的.当组件以提交"常规"ajax请求的形式出现时,这将导致麻烦.CommonsFileUploadDecoder正确的检查,这就是它在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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

就是这样(虽然保留了这个<renderer-kit>条目faces-config.xml).如果请求不是请求,则无需继续解码multipart.无论如何文件部分都不可用(并且javax.servlet.*当通过相同的功能可以获得时,也没有回到API的意义ExternalContext).


Kai*_*Kai 34

我遇到过同样的问题.这似乎是更关系到<p:commandButton><p:fileUpload>组成部分,因为它与工作<h:commandButton>(甚至使用Ajax).

你可以尝试:

<h:commandButton id="btnSubmit" actionListener="#{testManagedBean.insert}" value="Save">
    <f:ajax execute="@all" render="@form"/>
</h:commandButton> 
Run Code Online (Sandbox Code Playgroud)

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

编辑:

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

所以这是需要做的事情:

  • 创建一个新类 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");
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在您的底部添加以下行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>
    
    Run Code Online (Sandbox Code Playgroud)
  • 你准备好了!

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

如果这对您有用,请告诉我!

编辑

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

  1. 在Ajax的文件上传使用<p:fileUpload/>(加密类型:multipart/form-data)
  2. 阿贾克斯行动中<p:editRow/><p:wizard/>(加密类型:application/www-form-urlencoded)

第一个由渲染器处理,而第二个在原始代码中导致异常,因为渲染器尝试处理它不能处理的东西.通过代码中所做的更改,只有multipart/form-data表单由呈现器处理,因此不会发生异常.IMO显然是Primefaces来源中的一个错误.代码差异只是方法private boolean isMultiPartRequest(FacesContext context)及其在代码中的一次出现.很高兴我能帮到你!


Mar*_*o B 9

虽然这已经很老了并且已经回答了,但我想分享一些内容,以防你错过它:PrimeFaces 4+现在有一个上下文参数,您可以使用(在web.xml中)手动选择应该使用哪个上传器(本机) -servlet3或commons).您可以使用它来强制公共上传器像这样:

<context-param>
   <param-name>primefaces.UPLOADER</param-name>
   <param-value>commons</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

(当然,您仍然需要FileUploadFilter,如上所述和指南中所述).有关详细信息,请参阅PrimeFaces用户指南.