使用PDFBox将标题添加到现有PDF文件
我正在尝试将标头添加到现有的PDF文件中。 它可以工作,但现有PDF中的表头由字体的变化搞砸了。 如果我删除设置字体,则标题不会显示。 这是我的代码:
// the document PDDocument doc = null; try { doc = PDDocument.load( file ); List allPages = doc.getDocumentCatalog().getAllPages(); //PDFont font = PDType1Font.HELVETICA_BOLD; for( int i=0; i<allPages.size(); i++ ) { PDPage page = (PDPage)allPages.get( i ); PDRectangle pageSize = page.findMediaBox(); PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true,true); PDFont font = PDType1Font.TIMES_ROMAN; float fontSize = 15.0f; contentStream.beginText(); // set font and font size contentStream.setFont( font, fontSize); contentStream.moveTextPositionByAmount(700, 1150); contentStream.drawString( message); contentStream.endText(); //contentStream. contentStream.close();} doc.save( outfile ); } finally { if( doc != null ) { doc.close(); } } }`
基本上,您在当前版本1.8.2中遇到了PDFBox错误。
解决方法:
在使用字体之前,在创建新内容流之后添加页面资源的getFonts
调用:
PDPage page = (PDPage)allPages.get( i ); PDRectangle pageSize = page.findMediaBox(); PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true,true); page.getResources().getFonts(); // <<<<<<<< PDFont font = PDType1Font.TIMES_ROMAN; float fontSize = 15.0f; contentStream.beginText();
错误本身:
错误在PDResources.addFont
方法中,该方法是从PDPageContentStream.setFont
:
public String addFont(PDFont font) { return addFont(font, MapUtil.getNextUniqueKey( fonts, "F" )); }
它使用fonts
成员变量的当前内容来确定手头页面上新字体资源的唯一名称。 不幸的是,此成员变量在此时仍然可以 (并且在您的情况下)未初始化。 这导致MapUtil.getNextUniqueKey( fonts, "F" )
调用始终返回F0 。
然后在addFont(PDFont, String)
调用期间隐式初始化font
变量。
因此,如果不幸的是,该页面上已存在名为F0的字体,则它将替换为新字体。
经过您的PDF测试,这正是您的案例中发生的事情。 由于现有字体F0使用一些自定义编码,而替换字体使用标准字体,因此最初使用F0编写的文本现在看起来像乱码。
上面提到的解决方法隐式初始化了该成员变量,因此阻止了字体替换。
如果您计划在生产中使用PDFBox执行此任务,则可能需要报告该错误。
PS:正如上面的评论中所提到的,在inheritance资源的上下文中还有另一个要观察的错误。 它也应该引起PDFBox开发的关注。
PPS:手头的问题已经在PDFBox中针对版本1.8.3和2.0.0进行了修复,参见 PDFBOX-1753 。