如何使用 iTextSharp 将 XMP 元数据添加到现有 PDF 的每一页

How do I add XMP metadata to each page of an existing PDF using iTextSharp

到目前为止,所有示例似乎都涉及在创建新文档时添加元数据。我想使用现有的 PDF 并使用 stamper

将 GUID 添加到每个页面的 XMP

XMP 在 PDF 上下文中最常见的用法是为从 PDF 的根字典(也称为目录)引用的整个文档添加 XMP 流。

但是,如果您查阅 PDF 规范,您会注意到 XMP 可以在 PDF 中的许多其他对象的上下文中使用,页面级别就是其中之一。如果查看规范,您会发现 /Metadata 是页面字典中的可选键。它需要对 XMP 流的引用。

如果您要使用 iText 从头开始​​创建 PDF 文档,您将找不到添加此元数据的特定方法,但您可以使用 [=19= 中提供的通用 addPageDictEntry() ].您可以将 PdfName.METADATA 作为键传递,并将对已添加到 PdfWriter 的流的引用作为值传递。

您的问题不是关于从头开始创建 PDF,而是关于修改现有 PDF。在这种情况下,您还需要页面字典。这些词典很容易获得:

PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfDictionary page;
for (int p = 1; p <= n; p++) {
    page = reader.getPageN(p);
    // do stuff with the page dictionary
}

此片段取自 Rotate90Degrees 示例。在该示例中,我们查看 /Rotate 条目,它是一个数字:

PdfNumber rotate = page.getAsNumber(PdfName.ROTATE);

您需要查找 /Metadata 条目,它是一个流:

PRStream stream = (PRStream) page.getAsStream(PdfName.METADATA);

也许这个流是 null,在这种情况下,您需要添加一个 /Metadata 条目,如 AddXmpToPage 示例所示:

// We create some XMP bytes
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XmpWriter xmp = new XmpWriter(baos, new PdfDictionary());
xmp.close();
// We add the XMP bytes to the writer
PdfIndirectObject ref = stamper.getWriter().addToBody(new PdfStream(baos.toByteArray()));
// We add a reference to the XMP bytes to the page dictionary
page.put(PdfName.METADATA, ref.getIndirectReference());

如果有 XMP 流,您想保留它并向其中添加一些内容。

这是您获取 XMP 字节的方式:

byte[] xmpBytes = PdfReader.getStreamBytes(stream);

您对这些字节施展了 XML 魔法,产生了一个名为 newXmpBytes 的新 byte[]。您可以像这样用这些新字节替换原始字节:

stream.setData(newXmpBytes);

所有这些操作都是在驻留在 PdfReader 对象中的现有文件上完成的。您现在必须坚持这样的更改:

PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.close();
reader.close();