PrimeFaces 11 simple模式fileUpload提交时upload方法未触发问题
PrimeFaces 11 单文件上传功能异常排查
问题表现
- 表单标签
<h:form>配置enctype="multipart/form-data"属性时,后端绑定的upload()方法完全无法触发 - 移除enctype属性后,
upload()方法可正常进入,但绑定的uploadedFile字段取值始终为null - PrimeFaces官方提供的所有文件上传示例均无法正常运行,无适配PrimeFaces 11版本的现成排查方案
现有实现代码
页面body部分
<h:body> <h:form enctype="multipart/form-data"> <p:fileUpload value="#{fileUploadBean.uploadedFile}" mode="simple" skinSimple="true"/> <p:commandButton value="Submit" ajax="false" action="#{fileUploadBean.upload}" styleClass="p-mt-3 ui-button-outlined p-d-block"/> </h:form> </h:body>
后端FileUploadBean代码
@Component public class FileUploadBean { private UploadedFile uploadedFile; private UploadedFiles files; public void upload() { String fileName = uploadedFile.getFileName(); String contentType = uploadedFile.getContentType(); byte[] contents = uploadedFile.getContent(); // Or getInputStream() } public void uploadMultiple() { System.err.println("uploadMultiple"); if (files != null) { for (UploadedFile f : files.getFiles()) { FacesMessage message = new FacesMessage("Successful", f.getFileName() + " is uploaded."); FacesContext.getCurrentInstance().addMessage(null, message); } } } public void handleFileUpload(FileUploadEvent event) { UploadedFile uploadedFile = event.getFile(); System.err.println(uploadedFile.getFileName()); FacesMessage message = new FacesMessage("Successful", event.getFile().getFileName() + " is uploaded."); FacesContext.getCurrentInstance().addMessage(null, message); } public UploadedFile getUploadedFile() { return uploadedFile; } public void setUploadedFile(UploadedFile uploadedFile) { this.uploadedFile = uploadedFile; } public UploadedFiles getFiles() { return files; } public void setFiles(UploadedFiles files) { this.files = files; } }
web.xml相关配置
<context-param> <param-name>primefaces.UPLOADER</param-name> <param-value>auto</param-value> </context-param> <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> <!-- Map these files with JSF --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>
排查修复步骤
- 删除冗余的FileUploadFilter配置
PrimeFaces 10及以上版本已经内置了multipart请求解析能力,不需要手动注册org.primefaces.webapp.filter.FileUploadFilter。手动注册这个旧版过滤器会和Servlet 3.0+容器自带的multipart解析逻辑、PrimeFaces内置解析逻辑产生冲突,直接导致带multipart/form-data的请求解析失败,后端action方法无法触发。直接删除web.xml中该过滤器对应的<filter>和<filter-mapping>节点即可。 - 为Faces Servlet补充multipart配置
Servlet 3.0+规范下,接收multipart请求的Servlet必须显式配置<multipart-config>节点,否则容器不会解析请求中的文件内容,这也是移除enctype后方法能进入但文件对象为null的核心原因。在Faces Servlet的配置块中补充如下内容:<multipart-config> <!-- 单个文件大小上限,单位字节,示例配置为10MB --> <max-file-size>10485760</max-file-size> <!-- 整个请求大小上限,单位字节,示例配置为20MB --> <max-request-size>20971520</max-request-size> <!-- 内存写入阈值,超过该大小的文件会临时写入磁盘 --> <file-size-threshold>102400</file-size-threshold> </multipart-config> - 保留primefaces.UPLOADER参数为auto即可
PrimeFaces 11的auto模式会自动优先选择native上传策略,也就是直接调用容器本身的Servlet 3.0 multipart解析能力,不需要额外引入commons-fileupload依赖切换到commons上传模式,额外引入第三方包反而容易产生依赖冲突。 - 修正Bean的作用域配置
当前@Component注解默认是Spring单例作用域,在JSF请求处理过程中会产生线程安全问题,也会导致属性绑定失败。如果是Spring+JSF整合场景,将Bean作用域改为视图作用域:@Scope("view");如果是标准JSF环境,替换为@Named搭配@ViewScoped注解即可,不要用单例作用域处理请求级的文件上传逻辑。 - 页面配置校验
当前simple模式的<p:fileUpload>配置、ajax="false"的提交方式本身没有问题,不需要额外绑定fileUploadListener,上述配置修改完成后即可正常绑定文件对象。
配置修改完成后重启服务,带enctype="multipart/form-data"的表单即可正常提交,upload()方法可正常触发,uploadedFile对象也能正确读取文件名、文件类型和内容。
内容的提问来源于stack exchange,提问作者fknl
相关产品推荐
相关产品推荐

