Ms word 如何通过C通过OpenXML从Word(.Docx)中提取OLE文件#

Ms word 如何通过C通过OpenXML从Word(.Docx)中提取OLE文件#,ms-word,openxml,openxml-sdk,Ms Word,Openxml,Openxml Sdk,我想使用Openxml从“.docx”文件中抽象“OLE包”。我不知道怎么做,我也没有在官方的例子中找到任何关于它的例子。请帮帮我 这是我的尝试: 1.我通过“MS office 2016”构建了一个名为“Test.Docx”的Docx文件,并在“Test.Docx”中插入了一个“.zip”文件。我打开“OpenXMLSDK2.5Productivity Tool”观看“Test.docx”,我找到了这个(),但是我没有得到任何关于如何通过反射代码提取这个zip文件的信息 2.然后我尝试使用C#

我想使用Openxml从“.docx”文件中抽象“OLE包”。我不知道怎么做,我也没有在官方的例子中找到任何关于它的例子。请帮帮我

这是我的尝试: 1.我通过“MS office 2016”构建了一个名为“Test.Docx”的Docx文件,并在“Test.Docx”中插入了一个“.zip”文件。我打开“OpenXMLSDK2.5Productivity Tool”观看“Test.docx”,我找到了这个(),但是我没有得到任何关于如何通过反射代码提取这个zip文件的信息

2.然后我尝试使用C#和SharpCompress.dll来提取这个“.zip”文件,下面是代码:

class Program
{
    static void Main(string[] args)
    {
        string filepath = @"C:\Users\宇宙无敌帅小伙\Desktop\test.docx";

        OleFileTest(filepath);
    }

    public static void OleFileTest(string filepath)
    {
        try
        {
            using (WordprocessingDocument Docx = WordprocessingDocument.Open(filepath, true))
            {
                Body body = Docx.MainDocumentPart.Document.Body;

                IEnumerable<EmbeddedObjectPart> embd1 = Docx.MainDocumentPart.EmbeddedObjectParts;

                int cnt = 0;
                foreach (EmbeddedObjectPart item in embd1)
                {
                    System.IO.Stream dt = item.GetStream(FileMode.OpenOrCreate);
                    BinaryWriter writer = new BinaryWriter(dt);
                    byte[] bt = new byte[dt.Length];

                    using (FileStream fs = File.Open($"C:\\Users\\宇宙无敌帅小伙\\Desktop\\{cnt}.zip", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {

                        fs.Write(bt, 0, bt.Length);
                    }
                    cnt++;
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}
类程序
{
静态void Main(字符串[]参数)
{
字符串filepath=@“C:\Users\宇宙无敌帅小伙\桌面\测试.docx”;
OleFileTest(filepath);
}
公共静态文件测试(字符串文件路径)
{
尝试
{
使用(WordprocessingDocument Docx=WordprocessingDocument.Open(filepath,true))
{
Body Body=Docx.main documentpart.Document.Body;
IEnumerable embd1=Docx.MainDocumentPart.EmbeddedObjectParts;
int-cnt=0;
foreach(embd1中的EmbeddedObjectPart项)
{
System.IO.Stream dt=item.GetStream(FileMode.OpenOrCreate);
BinaryWriter=新的BinaryWriter(dt);
字节[]bt=新字节[dt.长度];
使用(FileStream fs=File.Open($“C:\\Users\\宇宙无敌帅小伙\\桌面\\{cnt}.zip”,FileMode.Create,FileAccess.ReadWrite,FileShare.ReadWrite)
{
fs.Write(bt,0,bt.Length);
}
cnt++;
}
}
}
捕获(例外e)
{
控制台写入线(e.Message);
}
}
}
但是我无法打开我提取的这个“.zip”文件。
有人能帮我吗?非常感谢

挑战在于,从
EmbeddedObjectPart
提取的二进制文件是而不是您的ZIP文件。它是一个结构化存储文件,其中包含您的ZIP文件

下面的单元测试演示了如何使用Microsoft Word提取作为OLE对象嵌入到Word文档(
“Resources\\ZipContainer.docx”
)中的ZIP文件(例如,
ZipContents.ZIP
)。请注意
Ole10Native.ExtractFile()
方法的用法,该方法从Word文档中嵌入的结构化存储文件(例如
oleObject1.bin
)中提取ZIP文件

使用System.IO;
使用代码片段;
使用DocumentFormat.OpenXml.Packaging;
使用Xunit;
命名空间CodeSnippets.Tests.OpenXml.Wordprocessing
{
公共类EmbeddedObjectPartTests
{
私有静态void提取文件(EmbeddedObjectPart部分,字符串destinationFolderPath)
{
//确定二进制文件的文件名和目标路径,
//结构化存储文件。
string binaryFileName=Path.GetFileName(part.Uri.ToString());
字符串binaryFilePath=Path.Combine(destinationFolderPath,binaryFileName);
//确保目标目录存在。
CreateDirectory(destinationFolderPath);
//将零件内容复制到结构化存储文件。
使用(Stream partStream=part.GetStream())
使用(FileStream FileStream=File.Create(二进制文件路径))
{
CopyTo(fileStream);
}
//从结构化存储文件中提取嵌入文件。
提取文件(binaryFilePath,destinationFolderPath);
//删除结构化存储文件。
Delete(二进制文件路径);
}
[事实]
public void CanExtractEmbeddedZipFile()
{
const string documentPath=“Resources\\ZipContainer.docx”;
常量字符串destinationFolderPath=“输出”;
字符串destinationFilePath=Path.Combine(destinationFolderPath,“ZipContents.zip”);
使用WordprocessingDocument wordDocument=
WordprocessingDocument.Open(documentPath,false);
//提取所有嵌入对象。
foreach(wordDocument.MainDocumentPart.EmbeddedObjectParts中的EmbeddedObjectPart部分)
{
提取文件(部分,destinationFolderPath);
}
True(File.Exists(destinationFilePath));
}
}
}
以下是Ole10Native类的要点,该类曾由Microsoft发布,但现在有点难找到:

使用系统;
使用System.IO;
使用System.Runtime.InteropServices;
使用System.Runtime.InteropServices.ComTypes;
使用System.Text.RegularExpressions;
命名空间代码片段.Windows
{
公共类Ole10Native
{
公共静态void提取文件(字符串sourceFilePath、字符串destinationFolder)
{
StgOpenStorage(sourceFilePath,null,STGM.READWRITE | STGM.SHARE_EXCLUSIVE,IntPtr.Zero,0,out-IStorage);
ProcessPackage(iStorage,destinationFolder);
发布对象(历史记录);
}
私有静态void ProcessPackage(IStorage pStg,字符串destinationFolder)
{
uint numReturned;
pStg.EnumElements(0,IntPtr.Zero,0,out IEnumSTATSTG pEnumStatStg);
var ss=新的STATSTG[1];
//在存储器中的STATSTG结构中循环。
做
{
//检索STATSTG结构
pEnumStatStg.Next(1,ss,未翻转);
如果(numReturned!=0)
{
//System.Runtime.InteropServices.ComTypes.STATSTG statsttm;
var bytT=新字节[4];
//检查pwcsName公司是否