- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想使用Openxml
从“.docx”
文件中抽象出“OLE package”
。我不知道该怎么做,并且在官方示例中没有找到任何相关示例。请帮助我。
这是我的尝试:
我通过“MS Office 2016”构建了一个名为“Test.docx”
的Docx文件,并将“.zip”
文件插入 “测试.docx”
。我打开“Open XML SDK 2.5 Productivity Tool”
来观看“Test.docx”
,我找到了这个( Figure 1 ),但我没有得到任何有关的信息如何通过反射代码提取这个zip文件。
然后我尝试使用 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);
}
}
}
但我无法打开我提取的这个“.zip”
文件。有人可以帮助我吗?非常感谢!
最佳答案
挑战在于您从 EmbeddedObjectPart
中提取的二进制文件不是您的 ZIP 文件。它是一个结构化存储文件,包含您的 ZIP 文件。
以下单元测试展示了如何提取嵌入到 Word 文档 ("Resources\\ZipContainer.docx"
) 中的 ZIP 文件(例如,ZipContents.zip
) code>) 作为 OLE 对象,使用 Microsoft Word。请注意 Ole10Native.ExtractFile()
方法的用法,该方法从嵌入在 Word 文档中的结构化存储文件(例如 oleObject1.bin
)中提取 ZIP 文件。
using System.IO;
using CodeSnippets.Windows;
using DocumentFormat.OpenXml.Packaging;
using Xunit;
namespace CodeSnippets.Tests.OpenXml.Wordprocessing
{
public class EmbeddedObjectPartTests
{
private static void ExtractFile(EmbeddedObjectPart part, string destinationFolderPath)
{
// Determine the file name and destination path of the binary,
// structured storage file.
string binaryFileName = Path.GetFileName(part.Uri.ToString());
string binaryFilePath = Path.Combine(destinationFolderPath, binaryFileName);
// Ensure the destination directory exists.
Directory.CreateDirectory(destinationFolderPath);
// Copy part contents to structured storage file.
using (Stream partStream = part.GetStream())
using (FileStream fileStream = File.Create(binaryFilePath))
{
partStream.CopyTo(fileStream);
}
// Extract the embedded file from the structured storage file.
Ole10Native.ExtractFile(binaryFilePath, destinationFolderPath);
// Remove the structured storage file.
File.Delete(binaryFilePath);
}
[Fact]
public void CanExtractEmbeddedZipFile()
{
const string documentPath = "Resources\\ZipContainer.docx";
const string destinationFolderPath = "Output";
string destinationFilePath = Path.Combine(destinationFolderPath, "ZipContents.zip");
using WordprocessingDocument wordDocument =
WordprocessingDocument.Open(documentPath, false);
// Extract all embedded objects.
foreach (EmbeddedObjectPart part in wordDocument.MainDocumentPart.EmbeddedObjectParts)
{
ExtractFile(part, destinationFolderPath);
}
Assert.True(File.Exists(destinationFilePath));
}
}
}
以下是 Ole10Native
类的要点,该类曾经由 Microsoft 发布,但现在有点难找到:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text.RegularExpressions;
namespace CodeSnippets.Windows
{
public class Ole10Native
{
public static void ExtractFile(string sourceFilePath, string destinationFolder)
{
StgOpenStorage(sourceFilePath, null, STGM.READWRITE | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out IStorage iStorage);
ProcessPackage(iStorage, destinationFolder);
Marshal.ReleaseComObject(iStorage);
}
private static void ProcessPackage(IStorage pStg, string destinationFolder)
{
uint numReturned;
pStg.EnumElements(0, IntPtr.Zero, 0, out IEnumSTATSTG pEnumStatStg);
var ss = new STATSTG[1];
// Loop through the STATSTG structures in the storage.
do
{
// Retrieve the STATSTG structure
pEnumStatStg.Next(1, ss, out numReturned);
if (numReturned != 0)
{
//System.Runtime.InteropServices.ComTypes.STATSTG statstm;
var bytT = new byte[4];
// Check if the pwcsName contains "Ole10Native" stream which contain the actual embedded object
if (ss[0].pwcsName.Contains("Ole10Native"))
{
// Get the stream objectOpen the stream
pStg.OpenStream(ss[0].pwcsName, IntPtr.Zero, (uint) STGM.READ | (uint) STGM.SHARE_EXCLUSIVE, 0,
out IStream pStream);
//pStream.Stat(out statstm, (int) STATFLAG.STATFLAG_DEFAULT);
IntPtr position = IntPtr.Zero;
// File name starts from 7th Byte.
// Position the cursor to the 7th Byte.
pStream.Seek(6, 0, position);
var ulRead = new IntPtr();
var filename = new char[260];
int i;
// Read the File name of the embedded object
for (i = 0; i < 260; i++)
{
pStream.Read(bytT, 1, ulRead);
pStream.Seek(0, 1, position);
filename[i] = (char) bytT[0];
if (bytT[0] == 0) break;
}
var path = new string(filename, 0, i);
// Next part is the source path of the embedded object.
// Length is unknown. Hence, loop through each byte to read the 0 terminated string
// Read the source path.
for (i = 0; i < 260; i++)
{
pStream.Read(bytT, 1, ulRead);
pStream.Seek(0, 1, position);
filename[i] = (char) bytT[0];
if (bytT[0] == 0) break;
}
// Unknown 4 bytes
pStream.Seek(4, 1, position);
// Next 4 byte gives the length of the temporary file path
// (Office uses a temporary location to copy the files before inserting to the document)
// The length is in little endian format. Hence conversion is needed
pStream.Read(bytT, 4, ulRead);
ulong dwSize = 0;
dwSize += (ulong) (bytT[3] << 24);
dwSize += (ulong) (bytT[2] << 16);
dwSize += (ulong) (bytT[1] << 8);
dwSize += bytT[0];
// Skip the temporary file path
pStream.Seek((long) dwSize, 1, position);
// Next four bytes gives the size of the actual data in little endian format.
// Convert the format.
pStream.Read(bytT, 4, ulRead);
dwSize = 0;
dwSize += (ulong) (bytT[3] << 24);
dwSize += (ulong) (bytT[2] << 16);
dwSize += (ulong) (bytT[1] << 8);
dwSize += bytT[0];
// Read the actual file content
var byData = new byte[dwSize];
pStream.Read(byData, (int) dwSize, ulRead);
// Create the file
var bWriter = new BinaryWriter(File.Open(Path.Combine(destinationFolder, GetFileName(path)),
FileMode.Create));
bWriter.Write(byData);
bWriter.Close();
}
}
} while (numReturned > 0);
Marshal.ReleaseComObject(pEnumStatStg);
}
private static string GetFileName(string filePath)
{
return Regex.Replace(filePath, @"^.*[\\]", "");
}
}
}
您可以在我的 CodeSnippets 中找到完整的源代码(包括 Ole10Native
类) GitHub 存储库。
关于c# - 如何通过C#通过OpenXML从Word(.Docx)中提取OLE文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59106776/
我的 C# 应用程序使用 OpenXML 创建一个 MSWord 文档,其中已经包含多个表。最后一部分是添加条形图。我找不到这个案例的好例子。 谢谢你的帮助! 我正在从头开始创建文档。从...开始:
我正在使用一个模板文档,该文档使用 CustomXmlBlocks 作为占位符来放置表格和其他信息。我需要能够以某种方式将图像放入其中一个 block 中......即使它首先放入运行中。 图像以字节
我正在以编程方式将 OpenXML 段落添加到 Word 文档中,并且稍后我需要能够将该段落识别为我的段落。关于如何做到这一点有什么想法吗?我尝试插入 XML 注释和扩展属性,但是当您将文档保存在 w
我想使用 openxml 删除一列,我能够清除单元格的内容,但一直无法找到删除列的文档,以便在删除列时向左移动其他单元格。如何使用 openxml 删除列,它将单元格向左移动? 最佳答案 我发现 Op
我找不到任何可以告诉我 txBody 标签中的文本是否带有项目符号的指标,您能否请我确定我应该使用哪个指标来了解文本是项目符号还是普通文本? -谢谢 最佳答案 在 txBody 标签内,您可以查找标签
我目前正在尝试使用 PHPWord 库及其模板系统来处理 docx 文件。我已经找到并更新了这个库的某人(不记得名字,但它并不重要)的路径,该库可以使用表(复制其行,然后在每一行上使用 PHPWord
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: Open Xml and Date format in Excel cell 我正在尝试从 DataGridView
我发现各种元素非常困惑。几乎每个元素似乎都有一个与之关联的“部分”,我不确定它们是如何粘合在一起的。 工作簿工作簿部分工作表工作表部分 我也对 DocumentFormat.OpenXml.Packa
我有一个存储在 Bitmap 对象中的图像,我想将其粘贴到 OpenXML 文档中。我尝试使用 MemoryStream 作为中间步骤,如下所示: ImagePart part = container
我试图理解 OpenXML 电子表格的内部文件内容。在一些文件中,我发现了这个字符串。其他标签具有相同的前缀。标签也可以有前缀 p: w: 等。 你能帮我理解这些前缀在标签中的含义吗? 最佳答案 您可
我的预期结果是: 你好 世界! 但是当我使用以下代码时: MainDocumentPart mainDocumentPart = package.AddMainDo
我需要将多个 .docx 文件收集到一个文件夹中,并将它们“链接”成一个将显示给用户的文档。 现在我已经阅读了 Brian Jones' article虽然听起来很有希望,但我遇到了一个问题。 当我使
我正在使用 OpenXml 生成 Excel 文件,在研究了大量不同的示例代码和 SDK Productivity Tool 后,终于得到了我想要的东西。只有一件事我无法回避。当我使用 Excel 打
我正在使用 openxml 创建 WordProcessingDocuments(工作正常,生成的 word 文档正是我想要的),现在我正在尝试使用 openxml Powertools 将这些新创建
我使用 OpenXML SDK 2.5 编写了一个 Word 文档,当我在 MS Office 中预览该文档时,该文档给出了预期的外观和格式。 现在我需要将此文档转换为 HTML 文档,我开始了解 O
我是 .net 编码员,我对 ColdFusion 真的很陌生。我编写了一个自动生成发票的 .dll 库。我需要使用 ColdFusion 应用程序中的库。我已经成功地将我的库中的类加载为 coldf
以前我发布了一个问题,如何将数据集中的数据填充到 excel 工作表中,而不是如何使用该数据创建图表。那篇文章不太走运,但现在我设法从数据集中填充数据,但也在努力根据该数据创建图表,我希望图表与我的数
快要被这个问题搞疯了。我确信它是如此简单,我只是错过了它,但我一生都无法找出如何使用 C# 中的 OpenXml SDK v2.0 更改 Word 2007 中的内容控件的内容。 我创建了一个带有纯文
我正在编写一个小应用程序,它将路径作为输入,然后获取该路径中的每个 docx 文件,用关键字替换每个超链接。 奇怪的是,我发现了两种超链接,第一种来自 WordprocessingDocument E
我有一段文字想在文档的中央出现。如何在docx4j中执行此操作?我目前正在使用: PPr paragraphProperties = factory.createPPr(); //cr
我是一名优秀的程序员,十分优秀!