PrimeFaces 11中AJAX模式下fileDownload功能异常的问题排查及解决咨询
首先,你的问题核心原因是FacesServlet的映射规则没有覆盖PrimeFaces动态资源请求路径,导致容器无法将/javax.faces.resource/dynamiccontent.properties这类请求交给FacesServlet处理,最终返回404错误页面——而这个错误页面被当作下载内容返回,所以文件只有1KB且无法打开。
对比官方示例的请求URL带有.xhtml后缀,说明官方的FacesServlet配置能处理这类带后缀的资源请求,而你的配置只能处理特定后缀(比如*.xhtml)的请求,不带.xhtml的dynamiccontent.properties请求就被容器直接返回404了。
解决步骤
1. 修改FacesServlet映射配置
你需要调整web.xml(或者使用Servlet注解),让FacesServlet能够处理/javax.faces.resource/*路径下的所有请求。
方式一:通过web.xml配置
找到你的FacesServlet映射部分,添加一个新的<url-pattern>:
<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>*.xhtml</url-pattern> <!-- 添加这一行,覆盖PrimeFaces资源路径 --> <url-pattern>/javax.faces.resource/*</url-pattern> </servlet-mapping>
方式二:通过Servlet 3.0+注解配置
如果你的项目使用注解配置FacesServlet,直接修改urlPatterns参数:
import javax.faces.webapp.FacesServlet; import javax.servlet.annotation.WebServlet; @WebServlet( name = "Faces Servlet", urlPatterns = {"*.xhtml", "/javax.faces.resource/*"}, loadOnStartup = 1 ) public class CustomFacesServlet extends FacesServlet { }
2. 检查过滤器或URL重写规则
如果你项目中使用了自定义过滤器或者URL重写工具(比如PrettyFaces),需要确保这些组件不会拦截/javax.faces.resource/*路径的请求,或者配置它们允许这类请求正常传递到FacesServlet。
3. 验证效果
修改配置后重启应用,再次点击下载按钮:
- 此时请求URL应该会被FacesServlet正确处理,不再返回404
- 下载的文件应该是正常大小且可以正常打开
额外说明
PrimeFaces从10.x版本开始支持AJAX模式的文件下载,你的后端StreamedContent代码是正确的,问题完全出在前端请求的路由配置上。只要让FacesServlet处理动态资源请求,就能解决这个问题。
内容的提问来源于stack exchange,提问作者XtremeBaumer

