使用 PDFBox 将页眉添加到现有 PDF 文件

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

我正在尝试向现有 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();
        }
    }
}`
java pdf pdfbox
2个回答
8
投票

本质上,您在当前版本 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

随后在

font
调用期间隐式初始化
addFont(PDFont, String)
变量。

因此,如果不幸的是该页面上已经存在名为 F0 的字体,它将被新字体替换。

对您的 PDF 进行测试后,这正是您的情况所发生的情况。由于现有字体 F0 使用一些自定义编码,而替换字体使用标准编码,因此最初使用 F0 编写的文本现在看起来像乱码。

上面提到的解决方法隐式初始化该成员变量,从而阻止字体替换。

如果您计划在生产中使用 PDFBox 来完成此任务,您可能需要报告该错误。

PS:正如上面的评论中提到的,在继承资源的上下文中还有另一个需要观察的错误。它也应该引起 PDFBox 开发人员的注意。

PPS:同时,当前的问题已在 PDFBox 1.8.3 和 2.0.0 版本中得到修复,参见。 PDFBOX-1753.


0
投票
        PDFont font = PDType1Font.COURIER_BOLD;
        float mainHeadingfontSize = 20;
        float subHeadingfontSize = 10;

        PDPageContentStream contentStream = new PDPageContentStream(doc, page);
        contentStream.setFont(font, mainHeadingfontSize);

        float pageWidth = page.getMediaBox().getWidth();
        float textWidth = font.getStringWidth("View FI Data") / 1000 * mainHeadingfontSize;
        float centerCoordinate = (pageWidth - textWidth) /2;
        float upperRightYCordinate = page.getMediaBox().getUpperRightY() - 50;

        contentStream.beginText();
        contentStream.newLineAtOffset(centerCoordinate, upperRightYCordinate);
        contentStream.setFont(font, mainHeadingfontSize);
        contentStream.showText("View FI Data");
        contentStream.endText();

        contentStream.setFont(font,subHeadingfontSize);
        contentStream.beginText();
        contentStream.newLineAtOffset(centerCoordinate - 300, upperRightYCordinate - 60);
        contentStream.showText("Profile");
        contentStream.endText();
        contentStream.close();
© www.soinside.com 2019 - 2024. All rights reserved.