使用 pdfbox 编辑 pdf 页面

Posted

技术标签:

【中文标题】使用 pdfbox 编辑 pdf 页面【英文标题】:Edit pdf page using pdfbox 【发布时间】:2013-07-15 03:23:01 【问题描述】:

我如何通过在我已经知道的像素中的特定位置写入来使用 java 和 pdfbox 编辑 pdf 页面?

我试过了,但它会覆盖:

PDDocument document = null;
try 
    document = PDDocument.load(new File("/x/x/x/mypdf.pdf"));
    PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(0);
    PDFont font = PDType1Font.HELVETICA_BOLD;
    PDPageContentStream contentStream = new PDPageContentStream(document, page);
    page.getContents().getStream();
    contentStream.beginText();
    contentStream.setFont(font, 12);
    contentStream.moveTextPositionByAmount(100, 100);
    contentStream.drawString("Hello");
    contentStream.endText();
    contentStream.close();
    document.save("/x/x/x/mypdf.pdf");
    document.close();
 catch (IOException e) 
    e.printStackTrace();
 catch (COSVisitorException e) 
    e.printStackTrace();

谢谢。

【问题讨论】:

【参考方案1】:

我知道怎么做,而不是使用 pdfbox 我使用iTextpdf,这是我使用的 java 代码:

package ma;

import java.io.*;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;

public class editPdf 

public static void main(String[] args) throws IOException,
        DocumentException 

    PdfReader reader = new PdfReader("/Users/Monssef/Desktop/mypdf.pdf");
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(
            "/Users/Leonidas/Desktop/mypdfmodified.pdf"));
    BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252,
            BaseFont.NOT_EMBEDDED);

        PdfContentByte over = stamper.getOverContent(1);

        over.beginText();
        over.setFontAndSize(bf, 10);
        over.setTextMatrix(107, 107);
        over.showText("page updated");
        over.endText();

    stamper.close();



【讨论】:

这不是已发布问题的正确答案。【参考方案2】:

您本可以使用 PDFBox,您所缺少的只是附加到页面。只需更改此行:

PDPageContentStream contentStream = new PDPageContentStream(document, page);

到:

PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true);

从 PDFBox 2.0 开始,boolean appendContent 已被 AppendMode APPEND 替换,因此之前的代码现在是:

PDPageContentStream contentStream = new PDPageContentStream(
    document, page, PDPageContentStream.AppendMode.APPEND, true
);

【讨论】:

【参考方案3】:

安妮塔是正确的。事实上,它工作得很好。我会添加这一行

page.getContents().getStream();

可能是多余的,并且 PDPage 在较新的版本中被贬低以支持 PDPageable (主要用于打印),但代码将用于您的目的而不会花费 iText 的费用(毕竟,您最初询问PDFBox)。

不要忘记包含 Anita 为在创建内容流时创建额外位而提供的修复:

PDPageContentStream contentStream = new PDPageContentStream(
        document, page, true, true);

您还应该记住,您可能会为放置在要覆盖文本的 pdf 顶部的每个打印部分创建和关闭流。您需要确保关闭流和文档,以便写入缓冲区,否则您将看不到您的更改。

另外,对于那些尝试这个的人,有几个选项可以从 apache 下载用于 pdfbox 的库。我认为最容易使用的是(目前)名为 pdfbox-app-1.8.10.jar 的那个(我目前甚至在我的 JSF 应用程序中都在使用它)。它已经包含其他硬连线到 pdfbox 中的库,您还需要下载这些库才能做任何有意义的事情。

【讨论】:

具有三个布尔参数的PDPageContentStream 构造函数是一个更好的选择。它试图确保在新流开始时图形状态处于默认状态。 我同意这一点。不是必需的,但是当您做每件需要做的事情时,很高兴知道图形处于什么状态。 OP通过忽略他写的“with java and pdfbox”部分回答了他自己的问题,这太糟糕了,他给出了一个他随后接受的itext答案。 Anita 给了他一个有效且符合问题的答案。

以上是关于使用 pdfbox 编辑 pdf 页面的主要内容,如果未能解决你的问题,请参考以下文章

PDFBOX 2.0.18 - 如何遍历 PDF 页面并检索特定字段

使用 PDFBox 从 PDF 文档中读取特定页面

创建具有默认“缩放到页面级别”的 PDF 文件 (pdfbox)

PDFBox:拆分 pdf 和输出前缀

PDFBox - 查找页面尺寸

Java PDFBox列出页面的所有命名目标