在PDF中查找、提取并保存嵌入的XML文件

编程语言 2026-07-11

我现在正在尝试从一个PDF中提取并保存一个嵌入的文件。这个PDF关乎德国的 “ZUGFeRD” 电子发票。PDF中有一个名为 zugferd-invoice.xmlfactur-x.xml 的XML文件,我需要把它从PDF中提取出来并保存为 Factur1234.xml

经过大量搜索,我找到了iText Core 9.5。现在我正尝试用它来解决我的问题。但是我找不到将XML文件保存的方法。

我只能用以下代码找到该文件:

PdfDocument pdfDocument = new PdfDocument(new PdfReader(SRC));
PdfNameTree names = pdfDocument.GetCatalog().GetNameTree(PdfName.EmbeddedFiles);

foreach (var entry in names.GetNames())
{
    if (entry.Key.ToString() == "zugferd-invoice.xml" || entry.Key.ToString() == "factur-x.xml")
    {
        //do something
    }
}

但我找不到将其保存为文件的方法。

或者我可以找到并保存PDF中的所有流。但是在那儿,我找不到获取流名称的方法,以便仅保存正确的文件。

这是我的尝试:

int numberOfPdfObject = pdfDocument.GetNumberOfPdfObjects();

for (int i = 1; i <= numberOfPdfObject; i++)
{
    PdfObject obj = pdfDocument.GetPdfObject(i);

    if (obj != null && obj.IsStream())
    {
        byte[] b;

        try
        {
            b = ((PdfStream)obj).GetBytes();
        }
        catch (PdfException)
        {
            b = ((PdfStream)obj).GetBytes(false);
        }

        using (FileStream fos = new FileStream(String.Format(DEST + "/extract_streams{0}.dat", i), FileMode.Create))
        {
            fos.Write(b, 0, b.Length);
        }
    }
}

如何仅保存名称正确的XML文件?

顺便提一下我的技术栈:

  • C#
  • Visual Studio 2026
  • iText 9.5.0
  • Windows 10 64位
  • VMware 25.0.1.25219725

祝你晚上愉快

Greg

解决方案

以下代码将使用iText Core 9.6(必须与9.5兼容)从PDF中检索并写出所有嵌入的文件。你可以按名称对zugferd进行筛选,但我预计发票中应该只有一个嵌入的文件。

private void DumpEmbeddedFiles(String srcDoc, String destFolder)
{
    using (PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcDoc)))
    {
        PdfDictionary catalog = pdfDoc.GetCatalog().GetPdfObject();
        PdfDictionary names = catalog.GetAsDictionary(PdfName.Names);
        if (names == null)
        {
            return;
        }

        PdfDictionary embeddedFiles = names.GetAsDictionary(PdfName.EmbeddedFiles);
        if (embeddedFiles == null)
        {
            return;
        }

        PdfArray nameArray = embeddedFiles.GetAsArray(PdfName.Names);
        if (nameArray == null || nameArray.IsEmpty())
        {
            return;
        }

        for (int i = 0; i < nameArray.Size(); i += 2)
        {
            PdfString fileDesc = nameArray.GetAsString(i);
            PdfDictionary fileSpec = nameArray.GetAsDictionary(i + 1);

            if (fileDesc == null || fileSpec == null)
            {
                continue;
            }

            PdfDictionary efDict = fileSpec.GetAsDictionary(PdfName.EF);
            if (efDict == null)
            {
                continue;
            }

            PdfStream stream = efDict.GetAsStream(PdfName.UF);
            if (stream == null)
            {
                stream = efDict.GetAsStream(PdfName.F);
            }
            if (stream == null)
            {
                continue;
            }

            PdfString fileName = fileSpec.GetAsString(PdfName.UF);
            if (fileName == null)
            {
                fileName = fileSpec.GetAsString(PdfName.F);
            }
            if (fileName == null)
            {
                fileName = fileDesc;
            }

            File.WriteAllBytes(System.IO.Path.Combine(destFolder, fileName.GetValue()), stream.GetBytes());
        }
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章