我正在使用PDFBox从现有的PDF模板构建文档,因此它会打开文件,向其中添加文本并保存。除了尝试使用外部TTF字体外,它运行良好。我尝试了不同的东西并搜索了2天的解决方案,但PDFBox上的数据并不多。
以下是使用字体"Tardy Kid"的一些代码,因为它不能被误认为是其他任何内容,并且不太可能是任何标准库的一部分。
代码执行正常,从println显示“TardyKid”(显示字体已加载且名称可获取),并显示文本 - 但它在Helvetica中。使用getStringWidth()
计算宽度的代码的更复杂部分似乎也表示宽度表的成功加载。它只是无法正确显示。
代码在较大程序的上下文中运行,该程序打开现有PDF文档(模板)并向其添加文本。除了
之外,这一切似乎都很好 public void setText ( PDDocument document, String text ) throws IOException {
int lastPage = document.getNumberOfPages() - 1;
PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(lastPage);
PDPageContentStream contentStream = null;
try {
contentStream = new PDPageContentStream(document,page,true,true,false);
File fontFile = new File(m_fontDir, "Tardy_Kid.ttf");
PDFont font = PDTrueTypeFont.loadTTF(document, fontFile);
Color color = new Color(196, 18, 47);
float x = 100f, y = 700f;
System.out.println(font.getBaseFont());
contentStream.setFont(font, 32);
contentStream.setNonStrokingColor(color);
contentStream.beginText();
contentStream.moveTextPositionByAmount(x,y);
contentStream.drawString(text);
contentStream.endText();
} finally {
if (contentStream != null) {
contentStream.close();
}
}
}
答案 0 :(得分:5)
我找到了答案。我不确定这是否是PDFBox中的错误,但如果您在同一页面上多次打开/关闭内容流(由PDPageContentStream返回),则无法正常工作。因此,当在页面上多次调用例程时,在setText例程内打开/关闭内容流不起作用。将流转移到例程之外并打开/关闭整个页面一次似乎可以解决这个问题(以及其他几个问题)。
在文档或示例代码中的任何地方都没有提到,并且最多也是非常微妙的。我会称之为一个错误,特别是因为它“有效”(不会抛出任何异常)但会在页面上创建不确定和/或错误的结果。
答案 1 :(得分:2)
我遇到了类似的问题,这个问题来自于在构建war文件时损坏了pdf模板文件的pom更新。
堆栈跟踪声明“无法读取嵌入式TTF的字体TimesNewRoman,Bold”这当然是在看到与“pushback size”相关的错误之后,我们设置了一个新的属性值以便过去(我看到的异常)供参考:org.apache.pdfbox.exceptions.WrappedIOException: Could not push back 480478 bytes in order to reparse stream. Try increasing push back buffer using system property org.apache.pdfbox.baseParser.pushBackSize
)。
我们花了一段时间,然而在爆炸战争并试图在战争中打开pdf文件后,我们注意到它已损坏,但源文件中的pdf文件没有损坏。
我们问题的根本原因是我们在资源文件夹的pom中添加了“过滤”。我们这样做是为了让我们可以使用一些反射来在健康检查页面中获取一些值,但是这会破坏pdf文件,我们从以下参考文献中找到了这些文件:https://bitbucket.org/petermr/xhtml2stm/issues/12/pdf-files-are-being-corrupted-at-some
以下是我们设置的过滤示例:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
我们的解决方案是从我们的pom中删除它,并返工我们如何获取健康页面的信息。
答案 2 :(得分:0)
多年后,随着 PDFBOX 接近 3.0.0 版本(但正式在 2.0.23 版本上),上述(特别是对于 Unicode)似乎是使用 PDType0Font.load() 完成的(在 2.0 的迁移指南中提到版本 here) 主要根据关于 SO 的问题。
我一直在为同样的问题苦苦挣扎,我发现在我的情况下,使用 PDDocument.saveIncremental() 时出了点问题 - 恕我直言 known to require careful consideration 与您需要调用 getCOSObject() 的事实有关。 setNeedToBeUpdated(true) 在许多不容易弄清楚的地方。因此,为了以防万一并缩小可能出现的问题,请检查简单的 PDDocument.save() 是否有效。
顺便说一句,我确实检查了其他建议,即打开和写入 PDPageContentStream 一次而不是多次,并检查字体本身是否被 Maven 资源过滤损坏,但事实并非如此。排除第二个问题,仅供参考,如果您需要LiberationSans-Regular TTF字体it is embedded in PDFBOX itself as a resource,无需将其添加到您自己的资源中。