为什么不在java servlet中创建pdf文档?

时间:2016-04-20 13:19:52

标签: java servlets pdf-generation itext pdfbox

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

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

文档已正确创建。

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

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

enter image description here

此代码无效:

enter image description here

1 个答案:

答案 0 :(得分:0)

请阅读文档。例如问题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保存在硬盘上。

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

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