web-dev-qa-db-ja.com

PrimeFaces 4.0 / JSF 2.2.xのAJAXでファイルのアップロードが機能しない-javax.servlet.ServletException:リクエストのコンテンツタイプはmultipart / form-dataではありません

重要:このスレッドで説明されている問題は fixedPrimeFaces 5.1 final(コミュニティリリース) released 2014年10月6日月曜日(今から数分前)。 JSF 2.2.8-02 (または api impl ).

そのため、たまたまそのバージョンを使用した場合(以上、言及する必要はありません)、この質問を読む必要さえありません。


Webアプリケーションを実行しています

  • GlassFish 4.0
  • モジャラ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>

テスト管理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.");
        }
    }
}

ファイルがファイルブラウザからアップロードされると、リスナーにファイル名が表示されます-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)

コマンドボタンの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リクエストでファイルをアップロードできませんでした。PrimeFacesDataTableの<p:rowEditor/>を使用した行の編集(たとえば、各行の画像とともに) AJAX based。

とにかくGlassFish4.0を保持したいです。また、GlassFish 4.0でMojarra 2.1.9をダウングレードしようとしましたが、例外で終わるバンドルの作成に失敗しました。 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>

問題はMojarraバージョンと一緒に静止したままです 2.2.5 (または api 、- implリリース済み 2014年1月8日。


Mojarraバージョン2.2.6(または apiimplリリース済み 2014年3月4日。問題はそのままです。


それでも機能しません PrimeFaces5.0 final released 2014年5月5日.

28
Tiny

同じ問題がありました。 _<p:commandButton>_(ajaxでも)で動作するため、_<p:fileUpload>_コンポーネントよりも_<h:commandButton>_に関連しているようです。

あなたが試すことができます:

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

なぜ、またはどのように機能するかを説明することはできませんが、問題は解決しました。もちろん欠点は、少なくともPrimefacesのメンバーがこの問題を修正するまでは、自分でスタイリングを行わなければならないことです。

[〜#〜] edit [〜#〜]

実際に2つのリクエストが行われていることが判明した場合、ソースを掘り下げてデバッグを行った後(_<p:wizard/>_で試しました)。最初のものは_multipart/form-data_で、実際にファイルのアップロードを行います。 BeanでfileUploadEventを起動します。ウィザードnextボタンを押すと、enctype _application/www-urlencoded_の別のフォームが送信されます。これにより例外が発生します。結論は、例外を抑制するコメントで書いたものとは異なり、有効な解決策であるということです。これは、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");
        }
    }
    _
  • _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>
    _
  • 準備ができました!

私たちは何をしましたか?メソッドisMultiPartRequest()を使用して、contentTypeが実際に_multipart/form-data_であるかどうかを確認する独自のFileUploadRendererを作成しました。これがtrueを返す場合にのみ、残りのコードが実行されます。それ以外の場合は何も起こりません。つまり、例外はスローされません。 Primefacesがこの問題を修正する場合、クラスを使用するには_faces-config.xml_から行を削除するだけです。

それがあなたのために働くかどうか教えてください!

[〜#〜] edit [〜#〜]

このコードは、指定された要求がmultipart/form-data型であるかどうかをチェックします。そうでない場合、実行は停止されます。とにかく、元のPrimefacesコードは継続します。前述したように、Primefacesコンポーネント内にファイルをアップロードすると、実際には2つのリクエストが行われます。

  1. _<p:fileUpload/>_を使用したAjax-FileUpload(enctype:_multipart/form-data_)
  2. _<p:editRow/>_または_<p:wizard/>_のAjaxアクション(enctype:_application/www-form-urlencoded_)

1つ目はレンダラーによって処理され、2つ目はレンダラーが処理できないものを処理しようとするため、元のコードで例外が発生します。コードに加えられた変更では、_multipart/form-data_フォームのみがレンダラーによって処理されるため、例外は発生しません。 IMOそれは明らかにPrimefacesのソースのバグです。コードの違いは、メソッドprivate boolean isMultiPartRequest(FacesContext context)とコード内でのその1回の出現だけです。よろしくお願いします!

34
Kai

Kaiが現在の質問で his answer で正当に指摘したように、問題はNativeFileUploadDecoderで使用されるFileUploadRendererがリクエストがmultipart/form-dataリクエストするかどうか。これにより、「通常の」ajaxリクエストが送信されているフォームにコンポーネントが存在する場合に問題が発生します。 CommonsFileUploadDecoderはそれを正しくチェックするため、ネイティブファイルアップロードパーサーがまだないJSF 2.1で正しく動作します。

カスタムレンダラーでこれを回避する彼のソリューションは正しい方向にありますが、アプローチは非常に不格好です。この特定のケースでは、わずか数行追加するだけで、200行を超えるクラス全体をコピー&ペーストする必要はまったくありません。代わりに、次のようにスーパーに委任する前に、そのクラスを正確に拡張し、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);
        }
    }

}

それだけです(<renderer-kit>faces-config.xmlエントリを保持します)。リクエストがmultipartリクエストでない場合、デコードを続行する意味はありません。とにかくファイル部分は利用できません(また、同じ機能がExternalContextを介してすぐに利用できる場合、javax.servlet.* AP​​Iにキャストバックする意味もありません)。

51
BalusC

これは古く、すでに答えられていますが、見逃した場合に備えて何かを共有したいと思いました:PrimeFaces 4+にはコンテキストパラメーターがあり、(web.xmlで)使用するアップローダーを手動で選択できます(ネイティブ-servlet3またはcommons)。これを使用して、次のようにcommons-uploaderを強制できます。

<context-param>
   <param-name>primefaces.UPLOADER</param-name>
   <param-value>commons</param-value>
</context-param>

(もちろん、上記およびガイドで説明されているFileUploadFilterが必要です)。詳細については、PrimeFacesユーザーガイドを参照してください。

9
Mario B

@BalusC-既存のFileUploadRendererを拡張するためのあなたの提案はとてもきれいです。ありがとう!

使用しているJSFのバージョンによっては、ランダムなiFrameポップアップが表示される場合があります。これはここで指摘されているバグです。 JAVASERVERFACES-284

これを修正する最初の試みで(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();
}
2
CodeMonkey

私は同じ問題を抱えていました。私の場合、データテーブルでprimefacesファイルアップローダーを使用しましたが、onRowEditを使用して既存の画像を変更しようとしましたが、上記と同じエラーが発生しました。次に、primefaces jarを5.1バージョンに変更しました。今はうまく動作しています。

0
user2938903