我正在尝试学习如何与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
,则效果很好。
我的问题是我想做的事是否可行,如果可以,怎么办?我想这一定有可能,而不仅仅是我做不到。如果不可能的话,我有什么选择?
您正在将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
...XML,这使我怀疑为什么Create()
...它仍会生成上面的第一个代码段完全相同的文档
Open()
甚至根本不需要输入Create()
。这里发生了几件事: