Это нельзя сделать в одном HTTP-ответе.Вам нужно разрешить клиенту отправлять два запроса, чтобы вы могли вернуть два ответа;один для устранения ошибок и другой для возврата PDF.Вам нужно всего лишь переделать метод действия bean-компонента и, возможно, добавить сервлет, обслуживающий файлы.
По сути, вам нужно сохранить PDF в локальном (временном) месте на диске или, возможно, в памяти, и позволить JSF условно отобразить некоторый JavaScript, который, в свою очередь, загружает PDF.Файл PDF можно загрузить через сервлет или какой-либо дополнительный контекст веб-приложения, указывающий на местоположение локального диска.
Например
<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
в качестве другого контекста веб-приложения в конфигурации сервера, то вы можете просто сохранить File
там, и он будет загружен.Но если вы не можете этого сделать, потому что не можете контролировать конфигурацию сервера, вам нужно создать сервлет, который сопоставляется с шаблоном URL-адреса /pdf/*
и выполняет в методе 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.