如何在Excel工作表中下载嵌入的PDF文件?

时间:2014-03-12 17:13:39

标签: c# excel pdf gembox-spreadsheet

所以我制作了这个程序来解析excel数据(使用Gembox)。但是,有时在我想下载/提取的一些工作表中有嵌入的PDF文件。我找不到检测和下载这些对象的方法。任何人都能指出我如何实现这一目标的正确方向?我知道Microsoft有一个Office文档提取器,可以读取excel文件,但它只能检测像word这样的Office文件。

我不是要求任何人为我做我的工作并写出代码,我只是迷失在这里,似乎是一个非常复杂的过程。

1 个答案:

答案 0 :(得分:0)

GemBox.Spreadsheet目前没有对此的支持,但您可以使用WindowsBase.dll程序集中的System.IO.Packaging命名空间来实现您的需求。 请尝试以下代码示例:

using System;
using System.IO;
using System.IO.Packaging;
using System.Text;

static class PdfExtractor
{
    public static void ExtractPdf(string packagePath, string destinationDirectory)
    {
        using (var package = Package.Open(packagePath))
        {
            int i = 1;
            foreach (var part in package.GetParts())
                if (part.ContentType == "application/vnd.openxmlformats-officedocument.oleObject")
                {
                    // PDF data is embedded into OLE Object package part.

                    var pdfContent = GetPdfContent(part.GetStream());
                    if (pdfContent != null)
                        File.WriteAllBytes(Path.Combine(destinationDirectory, "EmbeddedPdf" + (i++) + ".pdf"), pdfContent);
                }
        }
    }
    private static byte[] GetPdfContent(Stream stream)
    {
        // Every PDF file/data starts with '%PDF' and ends with '%%EOF'.
        const string pdfStart = "%PDF", pdfEnd = "%%EOF";

        byte[] bytes = ConvertStreamToArray(stream);

        string text = Encoding.ASCII.GetString(bytes);

        int startIndex = text.IndexOf(pdfStart, StringComparison.Ordinal);
        if (startIndex < 0)
            return null;

        int endIndex = text.LastIndexOf(pdfEnd, StringComparison.Ordinal);
        if (endIndex < 0)
            return null;

        var pdfBytes = new byte[endIndex + pdfEnd.Length - startIndex];
        Array.Copy(bytes, startIndex, pdfBytes, 0, pdfBytes.Length);

        return pdfBytes;
    }
    private static byte[] ConvertStreamToArray(Stream stream)
    {
        var buffer = new byte[16 * 1024];
        using (var ms = new MemoryStream())
        {
            int read;
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
                ms.Write(buffer, 0, read);

            return ms.ToArray();
        }
    }
}