如何配置和故障排除<p:fileUpload>
取决于PrimeFaces版本。
所有PrimeFaces版本
以下要求适用于所有PrimeFaces版本:
需要的enctype
属性<h:form>
必须设置为multipart/form-data
。如果不存在,ajax上传可能就可以了,但是一般的浏览器行为是不确定的,并且取决于表单的组成和Web浏览器的版本。只是始终将其指定为安全起见。
使用时mode="advanced"
(即ajax上传,这是默认设置),然后确保您<h:head>
在(主)模板中具有。这将确保正确包含必要的JavaScript文件。mode="simple"
(非ajax上传)不需要此功能,但这会破坏所有其他PrimeFaces组件的外观和功能,因此您也不想错过它。
使用mode="simple"
(即非ajax上传)时,必须在任何PrimeFaces命令按钮/链接上禁用ajax ajax="false"
,并且必须使用<p:fileUpload value>
with <p:commandButton action>
代替<p:fileUpload fileUploadListener>
(对于PrimeFaces <= 7.x)或<p:fileUpload listener>
(对于PrimeFaces> = 8.x)
因此,如果您要(自动)使用ajax支持上传文件(请注意<h:head>
!):
<h:form enctype="multipart/form-data">
<p:fileUpload fileUploadListener="#{bean.upload}" auto="true" /> // for PrimeFaces >= 8.x this should be listener instead of fileUploadListener
</h:form>
public void upload(FileUploadEvent event) {
UploadedFile uploadedFile = event.getFile();
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
或者,如果您要上传非ajax文件:
<h:form enctype="multipart/form-data">
<p:fileUpload mode="simple" value="#{bean.uploadedFile}" />
<p:commandButton value="Upload" action="#{bean.upload}" ajax="false" />
</h:form>
private UploadedFile uploadedFile; // +getter+setter
public void upload() {
String fileName = uploadedFile.getFileName();
String contentType = uploadedFile.getContentType();
byte[] contents = uploadedFile.getContents(); // Or getInputStream()
// ... Save it, now!
}
做注意到Ajax相关的属性,如auto
,allowTypes
,update
,onstart
,oncomplete
,等被忽略在mode="simple"
。因此,在这种情况下无需指定它们。
还要注意,您应该立即在上述方法内部读取文件内容,而不是在以后的HTTP请求调用的其他bean方法中读取文件内容。这是因为上载的文件内容是请求范围的,因此在以后的/不同的HTTP请求中不可用。任何在以后的请求中尝试读取它的尝试都很有可能最终会出现java.io.FileNotFoundException
在临时文件中。
PrimeFaces 8.x
配置与下面的5.x版本信息相同,但是如果未调用您的监听器,请检查是否调用了attriubute listener
(例如,对于8.x之前的版本)fileUploadListener
PrimeFaces 5.x
如果您使用的是JSF 2.2,并且不需要声明任何其他配置,faces-config.xml
则还声明您符合JSF 2.2版本。您根本不需要PrimeFaces文件上传过滤器。如果您不清楚如何根据所使用的目标服务器正确安装和配置JSF,请转至如何通过Maven正确安装和配置JSF库?和JSF Wiki页面的“安装JSF”部分。
但是,如果您尚未使用JSF 2.2并且无法升级(当已经在Servlet 3.0兼容容器中时应该毫不费力),那么您需要手动注册以下PrimeFaces文件上传过滤器web.xml
(它将解析多个零件请求并填写常规请求参数图,以便FacesServlet
可以继续照常工作):
<filter>
<filter-name>primeFacesFileUploadFilter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
</filter-mapping>
的<servlet-name>
值facesServlet
必须与相同的<servlet>
条目中的值完全匹配。因此,如果是例如,则需要对其进行相应的编辑以匹配。javax.faces.webapp.FacesServlet
web.xml
Faces Servlet
PrimeFaces 4.x
与PrimeFaces 5.x相同的故事也适用于4.x。
通过来获取上载的文件内容仅存在一个潜在问题UploadedFile#getContents()
。null
当使用本机API代替Apache Commons FileUpload时,它将返回。您需要UploadedFile#getInputStream()
改用。另请参见如何在MySQL中将p:fileUpload中上传的图像作为BLOB插入?
本机API的另一个潜在问题将是,当上传组件以某种形式存在时,在该表单上会触发一个不同的“常规” ajax请求,该请求不会处理上传组件。另请参见在PrimeFaces 4.0 / JSF 2.2.x中,文件上传不适用于AJAX-javax.servlet.ServletException:请求内容类型不是multipart / form-data。
通过切换到Apache Commons FileUpload也可以解决这两个问题。有关详细信息,请参见PrimeFaces 3.x部分。
PrimeFaces 3.x
该版本不支持JSF 2.2 / Servlet 3.0本机文件上传。您需要手动安装Apache Commons FileUpload,并在中显式注册文件上传过滤器web.xml
。
您需要以下库:
这些必须存在于webapp的运行时类路径中。使用Maven时,请确保它们至少在运行时范围内(默认的编译范围也不错)。手动携带JAR时,请确保将它们放在/WEB-INF/lib
文件夹中。
可以在上面的PrimeFaces 5.x部分中找到文件上传过滤器注册的详细信息。如果您使用的是PrimeFaces 4+,并且想显式使用Apache Commons FileUpload而不是JSF 2.2 / Servlet 3.0本机文件上传,那么您需要在上述库旁边并对以下上下文参数进行过滤web.xml
:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>
故障排除
如果仍然无法正常工作,这是与PrimeFaces配置无关的另一个可能原因:
只有当你使用PrimeFaces文件上传过滤器:还有一个Filter
在你的webapp它运行之前的PrimeFaces文件上传过滤器,并已通过例如呼叫消耗的请求主体getParameter()
,getParameterMap()
,getReader()
,等等。一个请求正文只能被解析一次。当您在文件上传过滤器执行其工作之前调用这些方法之一时,文件上传过滤器将获得一个空的请求正文。
要解决此问题,您需要将<filter-mapping>
文件上传过滤器的放在另一个过滤器之前web.xml
。如果请求不是multipart/form-data
请求,则文件上传过滤器将继续运行,好像什么都没有发生。如果您使用因使用注释而自动添加的过滤器(例如PrettyFaces),则可能需要通过web.xml添加显式排序。请参阅如何使用WAR中的注释定义servlet过滤器的执行顺序
仅当您使用PrimeFaces文件上传过滤器时:Filter
您的Web应用程序中就有另一个在PrimeFaces文件上传过滤器之前运行并已执行了RequestDispatcher#forward()
调用。通常,URL重写过滤器(例如PrettyFaces)会执行此操作。这将触发FORWARD
调度程序,但默认情况下,筛选器REQUEST
仅在调度程序上侦听。
要解决此问题,您需要将PrimeFaces文件上载过滤器放在转发过滤器之前,或者重新配置PrimeFaces文件上载过滤器以监听FORWARD
调度程序:
<filter-mapping>
<filter-name>primeFacesFileUploadFilter</filter-name>
<servlet-name>facesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
有一个巢<h:form>
。这在HTML中是非法的,并且未指定浏览器行为。浏览器通常不会在提交时发送预期的数据。确保您没有嵌套<h:form>
。这完全与表格的形式无关enctype
。只是根本不嵌套表格。
如果仍然有问题,请调试HTTP流量。打开网络浏览器的开发人员工具集(在Chrome / Firebug23 + / IE9 +中按F12键),然后检查“网络/网络”部分。如果HTTP部分看起来不错,则调试JSF代码。放置一个断点,FileUploadRenderer#decode()
然后从那里前进。
保存上传的文件
在最终使它起作用之后,您的下一个问题可能类似于“如何/在何处保存上传的文件?”。好吧,继续这里:如何在JSF中保存上传的文件。
web.xml
按照《 PrimeFaces用户指南》注册PrimeFaces上传过滤器。反正你读过吗?但是,那不能解释为什么mode="simple"
对您有用。