在PDF中查找、提取并保存嵌入的XML文件
我现在正在尝试从一个PDF中提取并保存一个嵌入的文件。这个PDF关乎德国的 “ZUGFeRD” 电子发票。PDF中有一个名为 zugferd-invoice.xml 或 factur-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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。