Загрузка файлов не работает с AJAX в PrimeFaces 4.0 / JSF 2.2.x-javax.сервлет.ServletException: тип содержимого запроса не является составной / form-data
важно : проблема, которая обсуждается в этом потоке, была основные по состоянию на PrimeFaces 5.1 финал (общий выпуск) освобожден в понедельник, 6 октября 2014 года (всего несколько минут назад). Я попытался на JSF 2.2.8-02 (или api, impl).
как таковой, если вам случилось использовать эту версию (или выше, не нужно упоминать), вам даже не нужно будет больше читать этот вопрос.
у меня есть веб-приложение, работающее на
- GlassFish 4.0
- Mojarra 2.2.4
- PrimeFaces 4.0 final
все, кроме загрузки файлов с помощью AJAX, работает хорошо. Этот следующий файл xhtml отправляет многопартийное содержимое с помощью AJAX-запроса, инициированного кнопкой команды PrimeFaces.
<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.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.access0(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.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.access0(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"
.
я понизил версию Mojarra до 2.1.9 в Tomcat 7.0.35. Он работал с этой версией Mojarra наряду с на основе схемы PrimeFaces 4.0 финал (и на основе схемы 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 абы. Я также пытался понижение Mojarra 2.1.9 в GlassFish 4.0, но ему не удалось создать пакеты, заканчивающиеся исключением. GlassFish 4.0, похоже, не работает с Mojarra ниже 2.2.x.
Итак, что ответственно за возникновение этого исключения - PrimeFaces или JSF? Просто запутался. Есть ли обходной путь для загрузки файлов с запросами AJAX в этой среде?
EDIT:
отображение фильтра в 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) освобожден 08 января 2014 года.
еще раз попробовал на версии Mojarra 2.2.6 (или api, impl) освобожден 04 марта 2014 года. Проблема остается нетронутой.
все еще не работает на основе схемы PrimeFaces 5.0 финал освобожден 05 мая 2014 года.
5 ответов
у меня была та же проблема. Кажется, это больше связано с <p:commandButton>
, чем <p:fileUpload>
компонент, так как он работает с <h:commandButton>
(даже с ajax).
вы можете попробовать:
<h:commandButton id="btnSubmit" actionListener="#{testManagedBean.insert}" value="Save">
<f:ajax execute="@all" render="@form"/>
</h:commandButton>
я не могу сказать вам, почему и как это работает, но это исправили проблему для меня. Недостатком, конечно, является то, что вы должны сделать стиль самостоятельно, по крайней мере, до ребята Primefaces исправляют эту проблему.
редактировать:
После рытья в источники и выполнение некоторой отладки, если выяснили, что на самом деле сделано два запроса (я пробовал в <p:wizard/>
). Первый-это multipart/form-data
тот, который фактически делает загрузку файла. Он запускает fileUploadEvent в Бобе. Я волшебники далее кнопка нажата другая форма с enctype application/www-urlencoded
представлен. Это вызывает исключение. Вывод состоит в том, что в отличие от того, что я написал в комментарии, подавление исключения является допустимым решением. Это можно даже сделать таким образом, что не включает в себя изменение Primefaces.банку, которая удобна, если ребята исправят проблему в будущей версии.
Итак, вот что нужно сделать:
- создать новый класс
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>
вы готовы иди!
что мы сделали? Мы создали собственный FileUploadRenderer, который проверяет, действительно ли contentType multipart/form-data
методом isMultiPartRequest()
. Только если это возвращает true, выполняется остальная часть кода. В любом другом случае ничего не произойдет, что означает, что исключение не будет выброшено. Если Primefaces устраняет эту проблему, вам просто нужно удалить строки из вашего faces-config.xml
использовать свой класс.
Дайте мне знать, если это работает для ты!
редактировать
этот код проверяет, соответствует ли данный запрос типу multipart/form-data. Если это не так, казнь прекращается. Исходный код Primefaces будет продолжен в любом случае. Как я уже упоминал выше, если вы загружаете файл внутри компонента Primefaces, на самом деле сделано два запроса:
- Ajax-FileUpload с помощью
<p:fileUpload/>
(enctype:multipart/form-data
) - действие Ajax в
<p:editRow/>
или<p:wizard/>
(enctype:application/www-form-urlencoded
)
первый обрабатывается визуализатором, а второй вызывает исключение в исходном коде, поскольку визуализатор пытается обработать то, на что он не способен. С изменениями, внесенными в код только multipart/form-data
формы обрабатываются визуализатором, поэтому никаких исключений не происходит. ИМО это явно ошибка в источниках Primefaces. Различия в коде-это просто метод private boolean isMultiPartRequest(FacesContext context)
и его одно появление в коде. Рад, что смог помочь. ты!
как справедливо указал Кай в ответ по текущему вопросу проблема вызвана NativeFileUploadDecoder
как FileUploadRenderer
не проверять, является ли запрос multipart/form-data
запрос или нет. Это вызовет проблемы, когда компонент присутствует в форме, в которой отправляется "обычный" запрос ajax. The 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
запрос. Части файла не будут доступны в любом случае (и нет смысла возвращаться к javax.servlet.*
API, когда та же функциональность легко доступна через ExternalContext
).
хотя это старый и уже ответил, я хотел поделиться чем-то, на случай, если вы пропустили его: PrimeFaces 4+ теперь имеет контекстный параметр, который вы можете использовать (в интернете.xml), чтобы вручную выбрать, какой загрузчик должен использоваться (native-servlet3 или commons). Вы можете использовать это, чтобы заставить commons-uploader так:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value>
</context-param>
(конечно, вам все еще нужен FileUploadFilter, как описано выше и в руководстве). Дополнительные сведения см. В руководстве пользователя PrimeFaces.
@BalusC-ваше предложение по расширению существующего FileUploadRenderer
- Это очень чистые. Спасибо!
в зависимости от версии JSF, которую вы используете, вы можете увидеть случайное всплывающее окно iFrame. Это ошибка, отмеченная здесь:JAVASERVERFACES-2843
в моей первой попытке исправить это (без необходимости обновления до 2.2.1) я просто спрятал iFrame с CSS.
#JSFFrameId {
visibility:hidden;
}
это сработало, но по какой-то причине дополнительные AJAX submits не будут срабатывать. Затем я позвонил немного скрипт для удаления 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();
}
У меня была такая же проблема, В моем случае я использовал загрузчик файлов primefaces в таблице данных, попытался изменить существующее изображение с помощью onRowEdit, что закончилось той же ошибкой, упомянутой выше. Затем я изменил банку primefaces на версию 5.1. Теперь он работает нормально.