【问题标题】:Returning a PDF file from a Java Bean to a JSP将 PDF 文件从 Java Bean 返回到 JSP
【发布时间】:2010-09-18 03:34:04
【问题描述】:

编辑:请参阅下面的答案中的my working code


简而言之:我有一个 JSP 文件,它调用 Java Bean 中的方法。此方法创建一个 PDF 文件,理论上,将其返回给 JSP,以便用户可以下载它。但是,在加载 PDF 时,Adobe Reader 会给出错误:文件不以 '%PDF-' 开头

详细说明: 至此,JSP 成功调用了该方法,创建了 PDF,然后出现了 JSP,将完成的 PDF 文件提供给用户。但是,只要 Adob​​e Reader 尝试打开 PDF 文件,就会出现错误:文件不以 '%PDF-' 开头。只是为了更好地衡量,我有在我的桌面上创建 PDF 的方法,以便我可以检查它;当我在 Windows 中正常打开它时,它看起来很好。那么为什么 JSP 的输出不一样呢?

要创建 PDF,我使用的是Apache FOP。我正在关注他们最基本的示例之一,除了将生成的 PDF 传递给 JSP 而不是简单地将其保存到本地机器。我一直在关注他们的basic usage patternthis example code

这是我的 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());
         }
    }
}

我意识到这是一个非常具体的问题,但任何帮助将不胜感激!

【问题讨论】:

    标签: java jsp pdf xsl-fo apache-fop


    【解决方案1】:

    只是猜测,但您检查过您的 JSP 页面返回的 MIME 类型吗?

    编辑:如果我真的阅读了您发布的代码,我会看到您确实设置了它,所以没关系:)

    edit2:你的 JSP 代码中的 JSP 标记之间的换行符不是最终会出现在输出流中吗?会不会抛出服务器返回的响应?我对 PDF 的格式一无所知,但它是否取决于文件中某些位置的某些“标记”字符? (返回的错误消息听起来确实如此)。

    【讨论】:

      【解决方案2】:

      我过去实现此类功能的方式是让 servlet 将 PDF 文件的内容作为流写入响应。我已经没有源代码了(我已经至少有一年没有做任何 servlet/jsp 工作了),但您可能想尝试以下方法:

      在 servlet 中,获取响应输出流的句柄。将响应的 mime 类型更改为“application/pdf”,并让 servlet 执行您在示例中的文件处理。只是,不是返回 File 对象,而是让 servlet 将文件写入输出流。查看文件 i/o 的示例,只需将任何 outfile.write(...) 行替换为 responseStream.write(...) 即可。刷新并关闭输出流并返回后,如果我没记错的话,浏览器应该能够从响应中获取 pdf。

      【讨论】:

        【解决方案3】:

        我同意matt b,可能是JSP 标签之间的空格。尝试放置指令

        <%@ page trimDirectiveWhitespaces="true" %>
        

        【讨论】:

        • trimDirectiveWhitespaces 听起来非常有用,尽管一些谷歌搜索显示它只是从 JSP 2.1 开始(所以它是相当新的)。
        【解决方案4】:

        好的,我得到了这个工作。我是这样做的:

        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());
                }
             }
         }
        

        感谢大家的意见!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-26
          • 1970-01-01
          相关资源
          最近更新 更多