FlyingSaucer ITextRenderer 完成错误(不平衡的保存/恢复和空白 PDF)

问题描述 投票:0回答:2

我将 Flying Saucer 与 IText 结合使用,以便从 HTML 文件生成 PDF,特别是利用

org.xhtmlrenderer.pdf.ITextRenderer
类。我的代码很简单。生成代码封装在这样的方法中:

/* PDfGenerator class only has ONE instance */
public PdfGenerator() {
    this.renderer = new ITextRenderer(); //This is a class variable that only gets instantiated ONCE
}

public void generatePDF(String outputFilePath, String htmlContent) {
    renderer.setDocumentFromString(htmlContent);
    renderer.layout();
    renderer.createPDF(new BufferedOutputStream(
          new FileOutputStream(new File(outputFilePath)), BUFFER_SIZE), true);
    renderer.finishPDF();
}

编辑:

我的生成器类实际上由 Spring 作为单例对象进行管理。我有一个管理器类,它有一个 ExecutorService 作为 PDF 生成任务的队列。该管理器使用单例生成器来生成对象。因此,我只实例化 ITextRenderer 一次并重用它。现在我将队列设置为同时操作最多 2 个线程。我刚刚意识到这可能是导致的原因,因为我遇到了两个线程使用我的一个渲染器来渲染两组单独的 PDF 的情况。

现在,我刚刚意识到我实际上在每次渲染时调用“完成”两次!一个在

createPDF()
errors 调用中(将 true 作为第二个参数传递),以及一个对
finishPDF()
的显式调用。

这已经运行了相当长一段时间了,并且它在大多数时间都成功生成了 PDF。我偶尔遇到两种不同类型的错误:

  1. 由于保存/恢复状态运算符不平衡而导致运行时异常。示例堆栈跟踪如下:

    java.lang.RuntimeException: Unbalanced save/restore state operators.
    at com.lowagie.text.pdf.PdfContentByte.restoreState(Unknown Source) ~[itext-2.0.8.jar:na]
    at org.xhtmlrenderer.pdf.ITextOutputDevice.setClip(ITextOutputDevice.java:737) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.paintPage(ITextRenderer.java:387) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.writePDF(ITextRenderer.java:348) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:315) ~[core-renderer-R8.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:280) ~[core-renderer-R8.jar:na]
    
  2. 生成的 PDF 有缺失/变形的部分,或者最坏的情况是空白页。

对于问题 2,我相当有信心这是由于调用 finishPDF() 两次造成的。然而,对于问题 1,它发生在执行 finishPDF() 之前,所以我实际上不知道这是否是导致问题的原因。

有人在使用 Flying Saucer 和 iText 时有处理这两个问题的经验吗?

java itext flying-saucer
2个回答
1
投票
我遇到的问题基本上是

在不同线程上同时访问相同的 ITextRenderer 实例,从而扰乱当前运行的 PDF 生成作业的处理。

我已经使 Executor 服务仅使用 1 个线程,并使生成作业按顺序进行,并且根据我的观察,只要一次处理一个,我就可以重用相同的 ITextRenderer。

我已经向 Flying Saucer 库的开发人员发送了询问以确认这一点,当他们回复时我将更新这篇文章。

顺便说一句,我只需要弄清楚使用 1 个线程和 1 个预实例化的 ITextRenderer 实例生成或使用多个线程但按线程实例化 ITextRenderer 是否更有效。


0
投票
感谢您接受的答案!我在服务中使用相同的 ITextRenderer 实例时遇到了同样的问题。

您收到飞碟库开发者的回复了吗?您是否知道哪种方法(1 个线程 1 个实例与每个线程 1 个实例)更高效?

© www.soinside.com 2019 - 2024. All rights reserved.