将PDF文件从Java Bean返回到JSP
-
03-07-2019 - |
题
编辑:请参阅我的工作代码在下面的答案中。
简而言之:我有一个JSP文件,它调用Java Bean中的方法。此方法创建PDF文件,理论上将其返回给JSP,以便用户可以下载它。但是,在加载PDF时,Adobe Reader会显示错误:文件不以'%PDF - '开头。
详细信息:到目前为止,JSP已成功调用该方法,创建了PDF,然后JSP显示为用户提供了已完成的PDF文件。但是,只要Adobe Reader尝试打开PDF文件,就会出错:文件不以'%PDF - '开头。为了更好的衡量,我有方法在我的桌面上创建PDF,以便我可以检查它;当我在Windows中正常打开它看起来很好。那么为什么JSP的输出不同呢?
要创建PDF,我正在使用 Apache FOP 。我正在关注他们最基本的一个示例,除了将生成的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());
}
}
}
我意识到这是一个非常具体的问题,但任何帮助都会非常感激!
解决方案
我过去实现此类功能的方法是让servlet将PDF文件的内容作为流写入响应。我不再有源代码了(自从我做了任何servlet / jsp工作以来至少已经有一年了),但是你可能想尝试一下:
在servlet中,获取响应输出流的句柄。将响应的mime类型更改为“application / pdf”,并让servlet执行示例中的文件处理。只有,而不是返回File对象,让servlet将文件写入输出流。查看文件i / o的示例,只需用responseStream.write(...)替换任何outfile.write(...)行,就应该设置为go。一旦你刷新并关闭输出流并返回,如果我没记错的话,浏览器应该能够从响应中获取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());
}
}
}
感谢大家的投入!
只是一个猜测,但是你检查了JSP页面返回的MIME类型吗?
编辑:如果我真的读过您发布的代码,我会看到您确实设置了它,所以没关系:)
edit2:JSP代码中的JSP标记之间的换行是否最终会在输出流中结束?这会甩掉服务器返回的响应吗?我对PDF的格式一无所知,但是它取决于某些“标记”。字符在文件中的某些位置? (返回的错误消息听起来像它)。
我同意 matt b ,也许是JSP标记之间的空格。尝试放置指令
<%@ page trimDirectiveWhitespaces="true" %>