Open XML SDK-使用MemoryStream作为docx持有者从模板(dotx)创建docx

dar*_*nte 6 templates memorystream corrupt docx openxml-sdk

我正在尝试dotx使用OpenXML2.5库从单词模板(。)创建一个.docx文件。更确切地说,我想跟随这个,但我想用一个打开文档MemoryStream的文件,而不是路径。

因此,在上面的链接中,方法是这样的:将模板文件复制到磁盘上的新文件中。以打开新文件WordProcessingDocument,将其类型更改为Document并添加对模板的引用(我不确定为什么这样做是必要的...)

我需要的是。从数据库获取我的模板作为字节数组。将数组复制到流中,并以形式打开WordProcessingDocument。然后执行与上述相同的操作。我不想在磁盘上使用临时文件,等等。我不明白的是为什么我应该在新文档中引用模板文件(实际上,检查docx存档中的xml文件,它只是添加了一个包含模板名称的xml节点...为什么?)

现在,我的问题是,如果我使用a MemoryStream而不是文件的物理路径,则导致docx损坏。我收到“ Microsoft Office无法打开此文件,因为某些部分丢失或无效 ”。如果我使用临时磁盘文件,则可以使用。为什么会这样呢?

简化后,我的代码如下所示:

byte[] result = null;
byte[] templateBytes = System.IO.File.ReadAllBytes("template.dotx");
using (MemoryStream templateStream = new MemoryStream())

{
    templateStream.Write(templateBytes, 0, (int)templateBytes.Length);

    using (WordprocessingDocument doc = WordprocessingDocument.Open(templateStream, true))
            {
                doc.ChangeDocumentType(WordprocessingDocumentType.Document);
                var mainPart = doc.MainDocumentPart;

                //Here I should create an AttachedTemplate object and assign a relationship id to it, which also implies
                //setting a "reference" to the template ? I'm not using files so there's nothing to "reference" anyway
                // If it's doing more than just putting a visual reference to the template file, then why limit the way of referencing the template
                // only by using the Uri to the file? Please take a look at the above link to see what I'm referring to.

                //Write some text in the file ....
                mainPart.Document.Save();

                File.WriteAllBytes("Result.docx", templateStream.ToArray());
            }
   }
Run Code Online (Sandbox Code Playgroud)

这使我的docx文件损坏。如果我切换MemoryStream到从磁盘打开新的docx文件(使用WordProcessingDocument该类的其他构造函数),那么它将起作用。我没有做错任何事情(例如在处理内存流之后尝试将结果写入文件),因此它应该给我相同的结果。

我的代码有什么问题?

谢谢

Mic*_*off 4

如果您将代码 File.WriteAllBytes 的最后一行从内部 using 块中取出,它应该可以正常工作。只需将该行放在外部 using 块的右大括号之前即可。