我正在尝试允许用户通过点击按钮下载生成的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页面
更新
当我从Servlet中删除行super.doGet(req, response);
时,这会将我重定向到空白页面,而不会下载pdf。
答案 0 :(得分:2)
请勿致电super.doGet
:那是什么导致&#34; GET不受支持&#34;错误。 doGet
的默认实现(即HttpServlet
中定义的super
类的默认实现是打印GET未定义的消息。因为默认情况下,您没有'#1}}。尚未对其进行定义(即没有超载doGet
方法)。所以当你致电super.doGet
时,它会用405标题填充response
。你不希望超类来运行其默认方法;您只希望重载方法运行。
在您致电super.doGet
后,您的其余功能将被包裹在try
空catch
中。我想可能,如果你要将错误输出到日志中,那就像&#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;