java - iText 7、htmlPDF 2 - DefaultFontProvider 的并行使用

标签 java parallel-processing itext itext7 html-pdf

我们正在基于 iText 7.1.2htmlPDF 2.0.2 转换邮件消息。转换是在静态方法中完成的,该方法由并行线程为每个基于 html 的消息调用。代码看起来像这样简化(流在finally block 中关闭):

ConverterProperties properties = new ConverterProperties();
FontProvider fontProvider = new DefaultFontProvider();
for (String font : ITEXT_FONTS) {
   FontProgram fontProgram = FontProgramFactory.createFont(font);
   fontProvider.addFont(fontProgram);
}
properties.setFontProvider(fontProvider);

fos = new FileOutputStream(targetFile);
HtmlConverter.convertToPdf(is, fos, properties);

for循环用于从位于类路径的Noto包中添加中文字体。在我们的环境中,我们现在有时会看到以下错误情况:

Caused by: java.lang.OutOfMemoryError: Java heap space
   at java.util.Arrays.copyOf(Arrays.java:3236)
   at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
   at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
   at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
   at com.itextpdf.io.util.StreamUtil.inputStreamToArray(StreamUtil.java:212)
   at com.itextpdf.html2pdf.resolver.font.DefaultFontProvider.addShippedFreeFonts(DefaultFontProvider.java:111)
   at com.itextpdf.html2pdf.resolver.font.DefaultFontProvider.<init>(DefaultFontProvider.java:97)
   at com.itextpdf.html2pdf.resolver.font.DefaultFontProvider.<init>(DefaultFontProvider.java:81)

问题是:

  • 每次调用时创建 DefaultFontProvider 是否合法,还是应该只有一个实例(例如,由于创建成本)?
  • 如果 DefaultFontProvider 仅初始化一次 -> 该实例是否线程保存?

提前致谢!

最佳答案

简短的回答是:请阅读文档。

问题 1 的答案

Is the creation of the DefaultFontProvider legit for every single call or should there be only one instance (e.g. because of the costs of creation)?

您应该像现在一样为每次转化创建一个新实例。字体提供程序与文档相关联,这在 FontProvider 基类的文档中进行了说明。尽管如果您重用字体提供程序,它仍然很可能有效,但这不是我推荐的方式。

您正在使用的 setFontProvider 方法的文档对此有明确说明:

Please note that FontProvider instances cannot be reused across several documents and thus as soon as you set this property, this ConverterProperties instance becomes only useful for a single HTML conversion.

回答问题2

If the DefaultFontProvider is initialized only once -> is this instance thread save?

无法保证线程安全。文档指导您仅使用 DefaultFontProvider 进行单次转换。

优化技巧

(以便我尝试应用它们)

  1. 查看 DefaultFontProvider(boolean, boolean, boolean) 构造函数。默认情况下,pdfHTML 加载标准 PDF 字体以及 pdfHTML 附带的字体。如果您确定手动添加的字体涵盖了 HTML 文件中使用的所有脚本,则可以将 false 传递给所有三个构造函数参数 (new DefaultFontProvider(false, false, false ))。但如果您不确定,请不要这样做,因为这可能会导致结果中丢失一些文本。或者将必要的字体添加到您的 Collection 中以确保确定。
  2. 重用FontProgram实例。它们是线程安全的,可用于许多文档的转换。但是,这是 iText 的默认行为,除了明确事实之外,这很可能不会改善您的情况。
  3. 如果您可以做到1.,那么如果您使用FontProvider的另一个实现,您也可以重用FontSet - 首先,创建您的DefaultFontProvider once 并添加所有字体once,然后通过 defaultFP 获取 FontSet 实例。 getFontSet(),之后您可以使用 new FontProvider(fontSet) 通过字体集创建字体提供程序 - 每次进行转换时都必须执行此操作(请参阅问题 1 的答案) )。

关于java - iText 7、htmlPDF 2 - DefaultFontProvider 的并行使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52813674/

相关文章:

java - 在java中获取任何文件、文件夹或驱动器的48x48图标大小

java - 文件类对象在服务器java中运行时不会删除文件

java - Itext:在绝对位置显示段落

c# - 使用 iTextSharp 和 PDFStamper 在 PDF 中使用不同的字体

java - 领域层和持久层的区别

java - 我可以使用 <http :auto-config=true> and <UsernamePasswordAuthenticationFilter> at the same time in spring security

r - R中的并行连接问题

bash - Matlab 和 gnu 并行

c++ - 我如何理解我在 openMP 中的代码?

java - iText如何同时使用PdfWriterPipeline和PdfSmartCopy?