Servlets 在primefaces项目中使用iText生成Pdf

Servlets 在primefaces项目中使用iText生成Pdf,servlets,pdf,itext,Servlets,Pdf,Itext,我试图允许用户通过单击按钮下载生成的pdf,但我不知道代码中的问题出在哪里 我有一个servlet public class PdfGeneratorServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse response) th

我试图允许用户通过单击按钮下载生成的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中的按钮是


以及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>

PDF发生器
com.project.servlets.PdfGeneratorServlet
1.
PDF发生器
/pdf/*
问题是当我点击链接时,没有文件下载,而是重定向到405页

更新


当我删除行
super.doGet(req,response)时
从Servlet将我重定向到一个空白页面,没有下载pdf。

不要调用
super.doGet
:这就是抛出“GET not supported”(获取不支持)错误的原因。
doGet
(即
HttpServlet
中定义的
super
类的默认实现是打印GET未定义的消息。因为默认情况下,您尚未定义它(即未重载
doGet
方法)因此,当您调用
super.doGet
时,它将用405个头填充
响应
。您不希望超类运行其默认方法;您只希望您的重载方法运行

调用
super.doGet
后,函数的其余部分将被包装在一个
try
中,其中包含一个空的
catch
。我认为,如果您将错误输出到日志中,可能类似于“已设置响应头”因为对
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响应outputstream直接传递到PDF编写器的
getInstance
方法中:

//set headers
PdfWriter.getInstance(document, new DataOutputStream(response.getOutputStream()));
...
(您可能还希望将writer保存到变量
PdfWriter writer=PdfWriter.getInstance(..);
)中,并可能对其执行一些操作

这样,您就不需要写入缓冲区、从缓冲区读取数据并最终写入响应。它只是将PDF直接写入响应。而且不需要手动刷新或关闭响应缓冲区。这样做意味着您无法再设置内容长度标题,但无论如何也不必设置该标题如果你弄错了,d会引起问题


此外,如果您首先在最顶端设置标题,那么即使遇到错误并且实际上没有生成有效的PDF,它也会被锁定为以PDF形式提供响应,因此,如果出现错误,您最终会得到一个空白页面,而不是一个空白页面PDF。因此,至少PDF应用程序将打开。它只会打开一个错误,如“无法打开此PDF;它可能已损坏。”

您发布了一条本地化消息。这是什么意思?这是否意味着“URL“xxx”不允许/支持请求的方法GET?”抱歉,是的,这是消息的意思,当请求完成时(在开发者工具-Google Chrome上),它显示了什么媒体类型?是
application/pdf
还是仅仅
text/html
?是否正确调用了
doGet()
方法,因此您会看到消息,“是的,这是servlet pdfgenerator”在服务器终端上(日志)?是的,我可以看到日志“是的,这是servlet pdfgenerator”,Google Chrome提到的“text/plain”是在代码
response.setContentType(“application/pdf”)的这一行之后(或之前)添加这一行
response.setContentType(“application/pdf”)
与众不同(只是为了显示下载对话框)?答案很好,但我有一点意见:人们之所以先将PDF字节写入内存是有原因的。一些浏览器无法很好地处理PDF。他们以固定大小的块读取数据,如果PDF文件的大小不是固定大小的倍数,则在文件末尾添加无意义的字节。解决这一问题的唯一方法是添加一个标头使用文件大小
response.setContentLength(pdfOutputStream.size());
来确定文件大小的唯一方法是首先在内存中创建PDF。既然您提到了它,我还记得IE6的那个问题。