Servlets 在primefaces项目中使用iText生成Pdf
我试图允许用户通过单击按钮下载生成的pdf,但我不知道代码中的问题出在哪里 我有一个servletServlets 在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
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的那个问题。