带有MemoryStream的Open XML WordprocessingDocument为0KB

问题描述 投票:1回答:2

我正在尝试学习如何与Microsoft的Open XML SDK结合使用。我按照他们的步骤进行操作,以了解如何使用FileStream创建Word文档,并且效果很好。现在,我只想在内存中创建一个Word文档,然后等待用户指定是否要保存文件。

This document by Microsoft表示如何使用MemoryStream处理内存中的文档,但是,该文档首先从现有文件加载并“转储”到MemorySteam中。我想要的是完全在内存中创建文档(而不是基于驱动器中的文件)。我以为可以实现以下代码:

// This is almost the same as Microsoft's code except I don't
// dump any files into the MemoryStream
using (var mem = new MemoryStream())
{
    using (var doc = WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true))
    {
        doc.AddMainDocumentPart().Document = new Document();
        var body = doc.MainDocumentPart.Document.AppendChild(new Body());
        var paragraph = body.AppendChild(new Paragraph());
        var run = paragraph.AppendChild(new Run());
        run.AppendChild(new Text("Hello docx"));

        using (var file = new FileStream(destination, FileMode.CreateNew))
        {
            mem.WriteTo(file);
        }
    }
}

但是结果是一个0KB的文件,Word无法读取。起初我以为是因为MemoryStream的大小,所以我给它提供了1024的初始大小,但结果却是相同的。另一方面,如果我将MemoryStream更改为FileStream,则效果很好。

我的问题是我想做的事是否可行,如果可以,怎么办?我想这一定有可能,而不仅仅是我做不到。如果不可能的话,我有什么选择?

c# .net-core ms-word openxml memorystream
2个回答
1
投票

您正在将mem传递给WordprocessingDocument.Create(),后者是根据[现在为空] MemoryStream创建文档的,但是,我不认为这会将MemoryStream关联为C0的后备存储文献。也就是说,mem只是文档的input,而不是output。因此,当您调用mem.WriteTo(file);时,mem仍为空(调试器将确认这一点)。

然后,链接文档确实说“您必须向[Open()]提供可调整大小的内存流”,这意味着该流将被写入,因此mem does可能成为后备存储但尚未写入任何内容,因为AutoSave property(您在AutoSave中指定了true的目标)尚未生效(强调我的意思)...

获得一个标志,该标志指示是否应保存零件当处置时。

[我看到Create()有一个WordprocessingDocument,并用原始代码替换为SaveAs() method ...

SaveAs()

...为我生成预期的文件。有趣的是,在调用FileStream之后,即使我插入了对using (var mem = new MemoryStream()) using (var doc = WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true)) { doc.AddMainDocumentPart().Document = new Document(); var body = doc.MainDocumentPart.Document.AppendChild(new Body()); var paragraph = body.AppendChild(new Paragraph()); var run = paragraph.AppendChild(new Run()); run.AppendChild(new Text("Hello docx")); // Explicitly close the OpenXmlPackage returned by SaveAs() so destination doesn't stay locked doc.SaveAs(destination).Close(); } 的调用,doc.SaveAs()doc.Save()仍然都是mem.Length,这确实表明mem.Position仅用于初始化。] >

我要注意的另一件事是,示例代码正在调用0,而您正在调用mem。关于这两种方法的区别,文档非常稀疏,但是我建议您尝试使用Open()创建文档...

Open()

... 但是

当我这样做时,Create()引发异常,大概是因为Create()没有数据。因此,似乎名称有些不解,因为Open()初始化了新的文档数据,而using (MemoryStream mem = new MemoryStream()) using (WordprocessingDocument doc = WordprocessingDocument.Open(mem, true)) { // ... } 期望了现有数据。我确实发现,如果我给Open()填充了充满随机垃圾的mem ...
Create()

...它仍会生成上面的第一个代码段完全相同的文档

XML,这使我怀疑为什么Open()甚至根本不需要输入Create()

0
投票

这里发生了几件事:

© www.soinside.com 2019 - 2024. All rights reserved.