在primefaces项目上使用iText生成Pdf

时间:2014-12-23 18:31:50

标签: servlets pdf itext

我正在尝试允许用户通过点击按钮下载生成的pdf,但我不知道我的代码中的问题在哪里

我有一个servlet

public class PdfGeneratorServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response)
        throws ServletException, IOException {
    super.doGet(req, response); 
    try {
         System.out.println("yes this is the servlet pdfgenerator");
        ByteArrayOutputStream pdfOutputStream =
             new ByteArrayOutputStream();

        // Create PDF represented by document and write
        // send outout to our output stream.  
        // Document has the size and margins.

        Document document = 
                  new Document(PageSize.A4, 50, 50, 50, 50);
        PdfWriter.getInstance(document, pdfOutputStream);

        // PDF metadata.  Please see Document class
        // documentation to see more metadata that
        // you can use.

        document.addTitle("Servlet sample");
        document.addAuthor("The Kahimyang Project");

        document.open();

        // Write a paragraph using with font.
        document.add(new Paragraph("PDF Writer",
            FontFactory.getFont(FontFactory.HELVETICA_BOLD, 20)));

        // Paragraphs can contains, tables, images,
        // text, chuck of text, etc.

        Paragraph paragraph1 = new Paragraph();
        Chunk text = new Chunk("Content to write",
            FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12));

        paragraph1.add(text);

        // the image url below is a sample image

        Image image =
                Image.getInstance(
                new URL("http://kahimyang.info/kauswagan/images/bribe-no.png"));

        // this would enable succedding text in the same
        // paragraph to wrap around the righ-aligned 
        // image

        image.setAlignment(Image.RIGHT | Image.TEXTWRAP);

        // Insert image to the same paragraph where we 
        // have our text above.
        paragraph1.add(image);

        // add the paragraph to our document
        document.add(paragraph1);


        Chunk hyperlink = new Chunk("The Kahimyang Project",
                FontFactory.getFont(
                       FontFactory.TIMES, 12, Font.UNDERLINE));

        // We add a hyperlink to chunk of text
        // The link below is a sample link.

        hyperlink.setAction(
                new PdfAction(new URL("http://kahimyang.info")));
        Paragraph paragraph2 = 
             new Paragraph("More text for your document.");

        // Add text with hyperlink to paragraph

        paragraph2.add(hyperlink);
        document.add(paragraph2);


        document.close();


        // Header
        response.setHeader("Expires", "0");
        response.setContentType("application/pdf");
        response.setContentLength(pdfOutputStream.size());

        // Write the PDF
        ServletOutputStream responseOutputStream = 
                            response.getOutputStream();
        responseOutputStream.write(pdfOutputStream.toByteArray());
        responseOutputStream.flush();
        responseOutputStream.close();

    } catch (Exception e) {
    }


}

   @Override
   public String getServletInfo() {
    return "My PDF Generator";
   }
}

我的xhtml按钮是

<h:outputLink value="pdf/khalid"> <h:outputText value="Generate PDF" /> </h:outputLink>

和我在web.xml中的servlet映射

<!-- PDF Servlet -->
<servlet>
    <servlet-name>PdfGenerator</servlet-name>
    <servlet-class>com.project.servlets.PdfGeneratorServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>PdfGenerator</servlet-name>
    <url-pattern>/pdf/*</url-pattern>
</servlet-mapping>

问题是我点击链接时没有文件下载但重定向到405页面 enter image description here

更新

当我从Servlet中删除行super.doGet(req, response);时,这会将我重定向到空白页面,而不会下载pdf。

1 个答案:

答案 0 :(得分:2)

请勿致电super.doGet:那是什么导致&#34; GET不受支持&#34;错误。 doGet的默认实现(即HttpServlet中定义的super类的默认实现是打印GET未定义的消息。因为默认情况下,您没有'#1}}。尚未对其进行定义(即没有超载doGet方法)。所以当你致电super.doGet时,它会用405标题填充response。你不希望超类来运行其默认方法;您只希望重载方法运行。

在您致电super.doGet后,您的其余功能将被包裹在trycatch中。我想可能,如果你要将错误输出到日志中,那就像&#34;已经设置了响应标题&#34;因为对super.doGet的调用已经将标题设置为内容类型HTML,状态405等,所以您尝试将内容类型更改为PDF将会在那里引发错误。

至于问题的其余部分,您还没有设置足够的标题。也就是说,你错过了这两个:

response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "filename=whatever.pdf");

而不是做:

ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
...
PdfWriter.getInstance(document, pdfOutputStream);
...
//set headers
ServletOutputStream responseOutputStream = response.getOutputStream();
responseOutputStream.write(pdfOutputStream.toByteArray());
responseOutputStream.flush();
responseOutputStream.close();

我建议只将servlet响应输出流直接传递给PDF编写器的getInstance方法:

//set headers
PdfWriter.getInstance(document, new DataOutputStream(response.getOutputStream()));
...

(您可能还想将编写器保存到变量PdfWriter writer = PdfWriter.getInstance(....);中),也许可以用它做点什么。

这样你就不会写入缓冲区,从缓冲区读取,最后写入响应。它只是直接将PDF写入响应。并且无需手动刷新或关闭响应缓冲区。这样做意味着您无法再设置内容长度标题,但无论如何都不需要,如果出错则会导致问题。

此外,如果您首先设置标题,位于最顶层,那么即使它遇到错误并且实际上没有构建有效的PDF,它也会被锁定为以PDF格式提供响应,因此而不是以空白页结束,如果出现错误,您最终会得到一个空白(即损坏的)PDF。所以至少PDF应用程序将打开。它只会打开一个错误,如&#34;无法打开此PDF;它可能是腐败的。&#34;