Возврат PDF-файла из Java Bean в JSP
-
03-07-2019 - |
Вопрос
Редактировать: Видишь мой рабочий код в приведенных ниже ответах.
Вкратце: У меня есть JSP-файл, который вызывает метод в Java Bean.Этот метод создает PDF-файл и теоретически возвращает его в JSP, чтобы пользователь мог его загрузить.Однако при загрузке PDF-файла Adobe Reader выдает сообщение об ошибке: Файл не начинается с '%PDF-'.
В деталях: Пока что JSP успешно вызывает метод, PDF-файл создан, а затем появляется JSP, чтобы предоставить пользователю готовый PDF-файл.Однако, как только Adobe Reader пытается открыть PDF-файл, он выдает сообщение об ошибке: Файл не начинается с '%PDF-'.Просто для пущей убедительности у меня есть метод create PDF на моем рабочем столе, чтобы я мог его проверить;когда я открываю его обычно в Windows, все выглядит нормально.Итак, почему выходные данные из JSP отличаются?
Чтобы создать PDF-файл, я использую Апачский ЩЕГОЛЬ.Я следую одному из их самых простых примеров, за исключением передачи результирующего PDF-файла в JSP вместо простого сохранения его на локальном компьютере.Я следил за их базовая схема использования и этот пример кода.
Вот мой JSP-файл:
<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>
<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.printreports.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>
<c:set scope="page" var="xml" value="${printReportsBean.download}"/>
Вот мой метод Java Bean:
//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();
public File getDownload() throws UtilException {
OutputStream out = null;
File pdf = new File("C:\\documents and settings\\me\\Desktop\\HelloWorld.pdf");
File fo = new File("C:\\somedirectory", "HelloWorld.fo");
try {
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
out = new FileOutputStream(pdf);
out = new BufferedOutputStream(out);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); //identity transformer
Source src = new StreamSource(fo);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
return pdf;
} catch (Exception e) {
throw new UtilException("Could not get download. Msg = "+e.getMessage());
} finally {
try {
out.close();
} catch (IOException io) {
throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
}
}
}
Я понимаю, что это очень специфическая проблема, но я был бы очень признателен за любую помощь!
Решение
В прошлом я реализовал функцию такого типа, чтобы сервлет записывал содержимое файла PDF в ответ в виде потока. У меня больше нет исходного кода (и прошло не менее года с тех пор, как я работал с сервлетом / jsp), но вот что вы можете попробовать:
В сервлете получите дескриптор потока вывода ответа. Измените MIME-тип ответа на «application / pdf», и пусть сервлет выполнит обработку файла, которая у вас есть в вашем примере. Только вместо того, чтобы возвращать объект File, пусть сервлет записывает файл в выходной поток. Посмотрите примеры файлового ввода-вывода и просто замените любые строки outfile.write (...) на responseStream.write (...), и вы должны быть готовы к работе. После того, как вы очистите и закроете выходной поток и выполните возврат, если я правильно помню, браузер сможет выбрать pdf из ответа.
Другие советы
Ладно, у меня все получилось.Вот как я это сделал:
JSP:
<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>
<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>
<%
// get report format as input parameter
ServletOutputStream servletOutputStream = response.getOutputStream();
// reset buffer to remove any initial spaces
response.resetBuffer();
response.setHeader("Content-disposition", "attachment; filename=HelloWorld.pdf");
// check that user is authorised to download product
printReportsBean.getDownload(servletOutputStream);
%>
Метод Java Bean:
//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();
public void getDownload(ServletOutputStream servletOutputStream) throws UtilException {
OutputStream outputStream = null;
File fo = new File("C:\\some\\path", "HelloWorld.fo");
try {
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
outputStream = new BufferedOutputStream(servletOutputStream);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outputStream);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); //identity transformer
Source src = new StreamSource(fo);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} catch (Exception e) {
throw new UtilException("Could not get download. Msg = "+e.getMessage());
} finally {
try {
outputStream.close();
} catch (IOException io) {
throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
}
}
}
Спасибо всем за их вклад!
Просто предположение, но вы проверили тип MIME, который возвращает ваша страница JSP?
edit: если бы я действительно прочитал код, который вы опубликовали, я бы увидел, что вы его установили, так что не берите в голову:)
edit2: Разве строки перевода тегов JSP в вашем коде JSP не попадут в поток вывода? Может ли это скинуть ответ, возвращаемый сервером? Я ничего не знаю о формате PDF, но зависит ли это от определенного " маркера " символы, находящиеся в определенных местах в файле? (Возвращенное сообщение об ошибке звучит так же, как и оно).
Я согласен с Мэттом Б , возможно, это пробелы между тегами JSP. Попробуйте поставить директиву
<%@ page trimDirectiveWhitespaces="true" %>