更改下载请求 URL,使其不会命中过滤器。前提是你不能只需将这些文件放入公共 Web 内容中,也不能将包含这些文件的文件夹添加为另一个上下文 https://stackoverflow.com/questions/1812244/simplest-way-to-serve-static-data-from-outside-the-application-server-in-a-java/1812356#1812356(例如,因为这些文件是动态生成的),一种方法是将所有下载服务代码从 JSF 托管 bean 移动到普通的 servlet。然后让链接 URL 或表单操作指向该 servlet。由于该请求不会命中FacesServlet
, the ExtensionsFilter
也不会被击中。
E.g.
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = request.getPathInfo().substring(1);
// Just do your job to get the File or InputStream, depending on the functional requirements.
// This kickoff example just allocates a file in the file system.
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimetype(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
(注意:如果您还没有使用 Servlet 3.0,只需替换@WebServlet
通过通常的 servlet 映射web.xml
;如果您仍然没有使用 Java 7,只需替换Files#copy()
按平常的InputStream
/OutputStream
循环样板)
像下面这样调用它(假设 JSP 上有旧版 JSF 1.2,考虑到您链接到 JSF 1.2 的 Tomahawk 源代码;因此不支持模板文本中的 EL)。
<h:outputLink value="#{request.contextPath}/files/#{bean.filename}">
<h:outputText value="Download #{bean.filename}" />
</h:outputLink>
如果下载需要额外的参数,只需使用<f:param>
:
<h:outputLink value="#{request.contextPath}/files/#{bean.filename}">
<f:param name="foo" value="#{bean.foo}" />
<f:param name="bar" value="#{bean.bar}" />
<h:outputText value="Download #{bean.filename}" />
</h:outputLink>
然后可以在 servlet 中获取,如下所示:
String foo = request.getParameter("foo");
String bar = request.getParameter("bar");
// ...