You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#列出PDF内嵌文件并获取其只读文件流?

刚好我之前做过类似的需求,用C#处理PDF内嵌文件最靠谱的方式是借助成熟的PDF处理库,比如iTextSharp(或者它的升级版本iText 7,这里先以经典的iTextSharp为例,API更直观易上手)。

首先你需要通过NuGet安装iTextSharp包:在NuGet包管理器里搜索iTextSharp并安装,或者用Package Manager Console执行:

Install-Package iTextSharp
1. 列出PDF中的内嵌文件

这个功能需要遍历PDF文档的目录字典,找到内嵌文件的列表并提取文件名:

using System.Collections.Generic;
using System.IO;
using iTextSharp.text.pdf;

public static List<string> ListPdfEmbeddedFiles(string pdfFilePath)
{
    var embeddedFileNames = new List<string>();

    // 打开PDF阅读器,自动释放资源
    using (var pdfReader = new PdfReader(pdfFilePath))
    {
        // 获取PDF的根目录字典
        PdfDictionary catalog = pdfReader.Catalog;
        // 获取Names字典,里面存储了各类命名对象(包括内嵌文件)
        PdfDictionary namesDict = catalog.GetAsDict(PdfName.NAMES);

        if (namesDict != null)
        {
            // 获取内嵌文件的字典
            PdfDictionary embeddedFilesDict = namesDict.GetAsDict(PdfName.EMBEDDEDFILES);
            if (embeddedFilesDict != null)
            {
                // 内嵌文件列表是一个数组,每两个元素为一组:文件名 + 文件引用
                PdfArray filesArray = embeddedFilesDict.GetAsArray(PdfName.NAMES);
                if (filesArray != null)
                {
                    for (int i = 0; i < filesArray.Size; i += 2)
                    {
                        // 提取文件名并加入列表
                        string fileName = filesArray.GetAsString(i).ToString();
                        embeddedFileNames.Add(fileName);
                    }
                }
            }
        }
    }

    return embeddedFileNames;
}

调用示例:

var files = ListPdfEmbeddedFiles(@"C:\your-file.pdf");
foreach (var file in files)
{
    Console.WriteLine($"内嵌文件:{file}");
}
2. 获取指定内嵌文件的只读文件流

找到目标文件后,我们可以提取它的二进制流,转成只读的MemoryStream返回:

using System.IO;
using System;
using iTextSharp.text.pdf;

public static Stream GetEmbeddedFileReadOnlyStream(string pdfFilePath, string targetFileName)
{
    using (var pdfReader = new PdfReader(pdfFilePath))
    {
        PdfDictionary catalog = pdfReader.Catalog;
        PdfDictionary namesDict = catalog.GetAsDict(PdfName.NAMES);

        if (namesDict != null)
        {
            PdfDictionary embeddedFilesDict = namesDict.GetAsDict(PdfName.EMBEDDEDFILES);
            if (embeddedFilesDict != null)
            {
                PdfArray filesArray = embeddedFilesDict.GetAsArray(PdfName.NAMES);
                if (filesArray != null)
                {
                    for (int i = 0; i < filesArray.Size; i += 2)
                    {
                        string currentFileName = filesArray.GetAsString(i).ToString();
                        // 匹配目标文件名(忽略大小写)
                        if (currentFileName.Equals(targetFileName, StringComparison.OrdinalIgnoreCase))
                        {
                            // 获取文件的间接引用
                            PdfIndirectReference fileRef = filesArray.GetAsIndirectObject(i + 1);
                            PdfDictionary fileDict = pdfReader.GetPdfObject(fileRef) as PdfDictionary;

                            if (fileDict != null)
                            {
                                // 获取内嵌文件的流字典
                                PdfDictionary embeddedFileDict = fileDict.GetAsDict(PdfName.EF);
                                if (embeddedFileDict != null)
                                {
                                    // 提取文件流
                                    PdfStream fileStream = embeddedFileDict.GetAsStream(PdfName.F);
                                    if (fileStream != null)
                                    {
                                        // 将流转为字节数组,再包装成只读MemoryStream
                                        byte[] fileBytes = PdfReader.GetStreamBytes(fileStream);
                                        return new MemoryStream(fileBytes).AsReadOnly();
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }
    }

    // 如果未找到目标文件,返回null
    return null;
}

调用示例:

using (var stream = GetEmbeddedFileReadOnlyStream(@"C:\your-file.pdf", "abc.data"))
{
    if (stream != null)
    {
        // 这里可以读取流内容,比如转成字符串或者写入本地文件
        using (var reader = new StreamReader(stream))
        {
            string content = reader.ReadToEnd();
            Console.WriteLine(content);
        }
    }
}

注意事项

  • 异常处理:实际使用时建议添加try-catch块,处理文件不存在、PDF损坏、权限不足等异常情况。
  • 许可证:iTextSharp用于商业项目需要购买商业许可证,非商业项目可免费使用;如果是商业场景,也可以考虑使用其他开源库如PdfSharp(不过PdfSharp处理内嵌文件的API相对繁琐一些)。
  • 编码问题:如果内嵌文件是文本类型,读取时要注意匹配对应的编码格式。

内容的提问来源于stack exchange,提问作者Wollmich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:43:13