这不能在一个 HTTP 响应中完成。您需要让客户端发送两个请求,以便您可以返回两个响应;一个清除错误,另一个返回 PDF。您只需要在 bean 的 action 方法中进行一些修改,并且可能添加一个文件服务 servlet。
基本上,您需要将 PDF 存储在本地(临时)磁盘位置或内存中,并让 JSF 有条件地渲染一些 JavaScript,然后再下载 PDF。 PDF 可以通过 servlet 或其他指向本地磁盘位置的 webapp 上下文下载。
例如
<h:form>
...
<h:commandButton value="Download" action="#{bean.submit}" />
<h:panelGroup rendered="#{not empty bean.pdfURL}">
<script>window.location = '#{bean.pdfURL}';</script>
</h:panelGroup>
</h:form>
与
public void submit() {
// Create PDF and store as byte[] in memory, or as File on disk.
// Then create an unique URL to the PDF.
pdfURL = externalContext.getRequestContextPath() + "/pdf/" + pdfID;
}
它应该在成功的表单提交上生成以下内容(这也应该清除验证错误!)
<script>window.location = '/contextname/pdf/uniquefilename.pdf';</script>
如果您在服务器配置中将/some/path/to/pdf 注册为另一个webapp 上下文,那么您只需将File 存储在其中即可下载。但如果你不能因为你无法控制服务器配置,那么你需要创建一个映射到/pdf/* 的 URL 模式的 servlet,并在 doGet() 方法中执行类似以下操作:
String filename = request.getPathInfo().substring(1);
File pdf = new File("/some/path/to/pdf", filename);
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(file.length()));
InputStream input = new FileInputStream(pdf);
OutputStream output = response.getOutputStream();
// Now just write input to output.