为啥不在 java servlet 中创建 pdf 文档? [复制]

Posted

技术标签:

【中文标题】为啥不在 java servlet 中创建 pdf 文档? [复制]【英文标题】:Why doesn'n create pdf-documents in java servlet? [duplicate]为什么不在 java servlet 中创建 pdf 文档? [复制] 【发布时间】:2016-08-13 05:04:38 【问题描述】:

我使用 iText/Pdfbox 创建 PDF 文档。当我使用这样的独立 Java 类创建 PDF 时,一切正常:

public static void main(String[] args)
...
...
...

文档已正确创建。

但我需要从 Servlet 创建一个 PDF 文档。我将代码粘贴到 get 或 post 方法中,在服务器上运行该 servlet,但没有创建 PDF 文档!

此代码作为独立应用程序工作:

此代码不起作用:

【问题讨论】:

将代码添加为文本,而不是屏幕截图 doesn't work 是什么意思?有什么例外吗? 您是否尝试将其关闭再打开? 首先选择技术:要么是 PdfBox 问题,要么是 iText 问题。您正在使用 PdfBox 代码,因此您的问题不应被标记为 iText 问题。请注意,iText 代码通常比 PdfBox 代码更容易阅读。尽管如此,我还是努力尝试阅读您的 PdfBox 代码。我看到您在文件系统上创建了一个文件。你为什么这样做?您不会向 response 对象发送任何内容。这意味着您的代码不应该工作,而您不应该感到惊讶它不工作。 我的意思是代码没有保存在磁盘上。我想把pdf保存在我的硬盘上。 【参考方案1】:

请阅读文档。比如How can I serve a PDF to a browser without storing a file on the server side?问题的答案

您当前正在文件系统上创建一个文件。您没有使用 response 对象,这意味着您没有向浏览器发送任何字节。这就解释了为什么浏览器中什么也没有发生。

这是一个简单的例子:

public class Hello extends HttpServlet 
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 
        response.setContentType("application/pdf");
        try 
            // step 1
            Document document = new Document();
            // step 2
            PdfWriter.getInstance(document, response.getOutputStream());
            // step 3
            document.open();
            // step 4
            document.add(new Paragraph("Hello World"));
            document.add(new Paragraph(new Date().toString()));
            // step 5
            document.close();
         catch (DocumentException de) 
            throw new IOException(de.getMessage());
        
    

但是,当您像这样直接发送字节时,某些浏览器会遇到问题。使用ByteArrayOutputStream 在内存中创建文件并告诉浏览器它可以在内容头中预期多少字节会更安全:

public class PdfServlet extends HttpServlet 

    protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException 
        try 
            // Get the text that will be added to the PDF
            String text = request.getParameter("text");
            if (text == null || text.trim().length() == 0) 
                 text = "You didn't enter any text.";
            
            // step 1
            Document document = new Document();
            // step 2
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter.getInstance(document, baos);
            // step 3
            document.open();
            // step 4
            document.add(new Paragraph(String.format(
                "You have submitted the following text using the %s method:",
                request.getMethod())));
            document.add(new Paragraph(text));
            // step 5
            document.close();

            // setting some response headers
            response.setHeader("Expires", "0");
            response.setHeader("Cache-Control",
                "must-revalidate, post-check=0, pre-check=0");
            response.setHeader("Pragma", "public");
            // setting the content type
            response.setContentType("application/pdf");
            // the contentlength
            response.setContentLength(baos.size());
            // write ByteArrayOutputStream to the ServletOutputStream
            OutputStream os = response.getOutputStream();
            baos.writeTo(os);
            os.flush();
            os.close();
        
        catch(DocumentException e) 
            throw new IOException(e.getMessage());
        
    

完整源代码见PdfServlet。你可以在这里试试代码:http://demo.itextsupport.com/book/

你在评论中写道

此演示将 PDF 文件写入浏览器。我想将 PDF 保存在我的硬盘上。

这个问题可以用两种不同的方式来解释:

    您希望将文件写入用户磁盘驱动器上的特定目录,而无需任何用户交互。这是禁止!如果服务器可以强制将文件写入用户磁盘驱动器的任何位置,这将是一个严重的安全隐患。 您希望显示一个对话框,以便用户可以将其磁盘驱动器上的 PDF 保存在他选择的目录中,而不仅仅是在浏览器中显示 PDF。在这种情况下,请仔细查看文档。您将看到这一行:response.setHeader("Content-disposition","attachment;filename="+ "testPDF.pdf"); 如果您希望 PDF 在浏览器中打开,您可以将 Content-disposition 设置为 inline,但在问题中,Content-disposition 设置为 attachment,这会触发对话框打开。

另见How to show a Save As dialog for a iText generated PDF?

【讨论】:

demo.itextsupport.com/book 这个演示将pdf写入浏览器。我想将pdf保存在我的硬盘上。 我会更新我的答案,因为您的问题可能会以不同的方式解释。 (你需要学习如何更准确地提问。) 是的,我需要作为结果标准对话框,询问用户他想在浏览器中显示 PDF 或保存到文件系统 (zip)。 非常感谢,它成功了。但我还不知道,如何将 pdf 转换为 zip 并获得标准对话框,询问用户他想在浏览器中显示 PDF 或以 zip 格式保存到文件系统?。 没有标准对话框可以做到这一点。您需要发送响应之前知道用户想要什么。这需要心灵感应或魔法。请以更科学的方式提问。例如:发布一个新问题,询问如何提供包含 PDF 文档的 ZIP 文件。不要使用评论部分发布后续问题。如果您不接受正确答案,请不要期待答案。

以上是关于为啥不在 java servlet 中创建 pdf 文档? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Java 在PDF中创建标记(Annotation)

使用JSON在java Servlet中创建json数组[重复]

如何读取文本文件(逐行)并使用输出作为 nameS 在 java 中创建 .pdf 文件?

为啥我们需要xampp在mysql中创建数据库??(用java连接它)

为啥java代码中创建的Android Button()必须使用(this)作为上下文?

IIS 7处理程序配置不在管道模式下使用App_Code源