C#列出PDF文件中的嵌入文件,并获取其中一个嵌入文件的文件流

时间:2018-03-21 14:19:59

标签: c# pdf itext

我可以使用LaTeX创建包含嵌入文件的PDF,例如:

\usepackage{embedfile}

\embedfile{abc.data}
\embedfile{def.data}

使用Acrobat Reader我可以再次提取两个数据文件。

但我怎么能用C#做到这一点?

  • 如何列出嵌入PDF中的文件,类似于目录列表?
  • 如何将文件流(只读)获取到PDF中的某个嵌入文件?

1 个答案:

答案 0 :(得分:0)

使用iTextSharp-LGPL PDF库,我能够解决它。

列出嵌入的文件名

public static string[] ListEmbeddedFileNames(string pdfFileName)
{
    string[] fileNames = new string[0];
    var reader = new iTextSharp.text.pdf.PdfReader(pdfFileName);
    if (reader != null)
    {
        var root = reader.Catalog;
        if (root != null)
        {
            var names = root.GetAsDict(iTextSharp.text.pdf.PdfName.NAMES);
            if (names != null)
            {
                var embeddedFiles = names.GetAsDict(iTextSharp.text.pdf.PdfName.EMBEDDEDFILES);
                if (embeddedFiles != null)
                {
                    var namesArray = embeddedFiles.GetAsArray(iTextSharp.text.pdf.PdfName.NAMES);
                    if (namesArray != null)
                    {
                        int n = namesArray.Size / 2; // I don't understand why I have to divide by 2
                        fileNames = new string[n];
                        for (int i = 0; i < n; i++) fileNames[i] = namesArray[2 * i].ToString();
                    }
                }
            }
        }
        reader.Close();
    }
    return fileNames;
}

获取嵌入式文件流

public static Stream GetEmbeddedFileStream(string pdfFileName, string embeddedFileName)
{
    byte[] data = GetEmbeddedFileData(pdfFileName, embeddedFileName);
    if (data == null)
        return null;
    else
        return new MemoryStream(data);
}

public static byte[] GetEmbeddedFileData(string pdfFileName, string embeddedFileName)
{
    byte[] attachedFileBytes = null;
    var reader = new iTextSharp.text.pdf.PdfReader(pdfFileName);
    if (reader != null)
    {
        var root = reader.Catalog;
        if (root != null)
        {
            var names = root.GetAsDict(iTextSharp.text.pdf.PdfName.NAMES);
            if (names != null)
            {
                var embeddedFiles = names.GetAsDict(iTextSharp.text.pdf.PdfName.EMBEDDEDFILES);
                if (embeddedFiles != null)
                {
                    var namesArray = embeddedFiles.GetAsArray(iTextSharp.text.pdf.PdfName.NAMES);
                    if (namesArray != null)
                    {
                        int n = namesArray.Size;
                        for (int i = 0; i < n; i++)
                        {
                            i++;
                            var fileArray = namesArray.GetAsDict(i);
                            var file = fileArray.GetAsDict(iTextSharp.text.pdf.PdfName.EF);
                            foreach (iTextSharp.text.pdf.PdfName key in file.Keys)
                            {
                                string attachedFileName = fileArray.GetAsString(key).ToString();
                                if (attachedFileName == embeddedFileName)
                                {
                                    var stream = (iTextSharp.text.pdf.PRStream)iTextSharp.text.pdf.PdfReader.GetPdfObject(file.GetAsIndirectObject(key));
                                    attachedFileBytes = iTextSharp.text.pdf.PdfReader.GetStreamBytes(stream);
                                    break;
                                }
                            }
                            if (attachedFileBytes != null) break;
                        }
                    }
                }
            }
        }
        reader.Close();
    }
    return attachedFileBytes;
}

我通过在嵌入文件上计算MD5校验和来检查我的解决方案。