使用iText打印对话框Pdf打印

时间:2017-01-17 05:21:22

标签: java pdf jsf itext

我正在使用 iText 创建PDF文件并使用以下代码进行打印:

Document iText_xls_2_pdf = new Document(PageSize.A4.rotate());
PdfWriter writer = PdfWriter.getInstance(iText_xls_2_pdf, response.getOutputStream());
iText_xls_2_pdf.open();

PdfAction action = new PdfAction(PdfAction.PRINTDIALOG);
writer.setOpenAction(action);
iText_xls_2_pdf.close();

第一次工作正常,即按预期打开打印对话框。 一旦用户关闭打印对话框并再次调用相同的代码,它就不会执行任何操作。

我在这里做错了吗?

注意:我正在 servlet doGet方法中执行此操作。

1 个答案:

答案 0 :(得分:0)

首先:您用于添加打开操作的代码是正确的。打开正在创建的PDF文档的任何PDF查看器都应触发打印对话框。

您知道您的iText代码是正确的,因为它在第一次打开PDF时有效。在您的情况下,这发生在浏览器中。目前还不清楚使用哪种PDF查看器:Firefox中的pdf.js? Chrome的PDF查看器?在Apple上预览? Adobe Reader?

  

注意:您不应该假设每个PDF查看器都实现了完整的PDF规范。一些观众忽略了开放动作,其他观众甚至不知道PrintDialog动作是什么。

您写道:一旦用户关闭了打印对话框并再次调用相同的代码,它就无法执行任何操作。

这是一种奇怪的放置方式。用户无需触发代码。该操作由打开操作触发,而不是通过单击某个按钮或选择某个菜单选项。如果您在说“再次调用相同代码”时解释您的意思,这将有所帮助。

现在,让我们假设“再次调用相同的代码”相当于刷新/重新加载页面。在这种情况下,PDF可能永远不会重新打开,因为它还没有过期。也许浏览器中的PDF查看器说:“嘿,我现在显示的文档,与我在缓存中的文档相同。我不需要重新打开它。”如果文档永远不会重新打开,没有理由再次触发打开操作。

当您将PDF提供给浏览器时,您要设置哪些标题?

您可以尝试在doGet()方法的适当位置添加这些行:

response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
    "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/pdf");
response.setContentLength(baos.size());

请注意,baosByteArrayOutputStream。这样做是错误的:

PdfWriter writer = PdfWriter.getInstance(iText_xls_2_pdf, response.getOutputStream());

你应该这样做:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(iText_xls_2_pdf, baos);
// do a lot of other stuff

最后(特别是之后设置标题),您将内容写入OutputStream对象的response

OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();

请参阅官方常见问题解答:How can I serve a PDF to a browser without storing a file on the server side?

如果所有这些都无济于事,则问题是由客户端的问题引起的。在这种情况下,你的问题没有答案。我们只能告诉你,你没有做错任何事。这是添加打开操作的正确方法:

PdfAction action = new PdfAction(PdfAction.PRINTDIALOG);
writer.setOpenAction(action);

如果这不起作用,您可以在Stack Overflow上获得的唯一答案是:“您的代码是正确的”(前提是您遵循ByteArrayOutputStream和HTTP标头上的建议)。