简体   繁体   English

如何将通过OpenXML从模板创建的Word文档转换为MemoryStream?

[英]How to convert Word document created from template by OpenXML into MemoryStream?

I need to return document as MemoryStream in ASP.NET controller method to download it at web page. 我需要使用ASP.NET控制器方法将文档作为MemoryStream返回,以将其下载到网页上。 I don't want to save this document on the file, and then read it as MemoryStream and return. 我不想将此文档保存在文件上,然后将其读取为MemoryStream并返回。 Note: overload method WordprocessingDocument.CreateFromTemplate(template) do not have stream option vs WordprocessingDocument.Create(stream, ...) 注意:与WordprocessingDocument.Create(stream,...)相比,重载方法WordprocessingDocument.CreateFromTemplate(template)没有流选项。

Solution with saving temp file is below. 保存临时文件的解决方案如下。

    public static MemoryStream GetWordDocumentFromTemplate()
    {
        string tempFileName = Path.GetTempFileName();
        var templatePath = AppDomain.CurrentDomain.BaseDirectory + @"Controllers\" + templateFileName;

        using (var document = WordprocessingDocument.CreateFromTemplate(templatePath))
        {
            var body = document.MainDocumentPart.Document.Body;

            //add some text 
            Paragraph paraHeader = body.AppendChild(new Paragraph());
            Run run = paraHeader.AppendChild(new Run());
            run.AppendChild(new Text("This is body text"));

            OpenXmlPackage savedDoc = document.SaveAs(tempFileName); // Save result document, not modifying the template
            savedDoc.Close();  // can't read if it's open
            document.Close();
        }

        var memoryStream = new MemoryStream(File.ReadAllBytes(tempFileName)); // this works but I want to avoid saving and reading file

        //memoryStream.Position = 0; // should I rewind it? 
        return memoryStream;
    }

Unfortunately it doesn't seem possible; 不幸的是,这似乎是不可能的。 if you Go To Definition on "SaveAs" and drill down as far as you can, you get to: 如果转到“另存为”上的“定义”并尽可能深入地查找,则可以:

protected abstract OpenXmlPackage OpenClone(string path, bool isEditable, OpenSettings openSettings); 受保护的抽象OpenXmlPackage OpenClone(字符串路径,bool isEditable,OpenSettings openSettings);

So it looks like the raw string XML is constructed at runtime and saved to a file internally, and there is no method that just yields the raw string (or stream). 因此,看起来原始字符串XML是在运行时构造的,并在内部保存到文件中,并且没有任何方法可以产生原始字符串(或流)。

Found answer which works without saving to intermediate temp file. 找到了无需保存到中间临时文件即可工作的答案。 Trick is to open template for editing, use accessible stream, change document type from template to document, and return this stream. 技巧是打开模板进行编辑,使用可访问的流,将文档类型从模板更改为文档,然后返回此流。

public static MemoryStream GetWordDocumentStreamFromTemplate()
{
    var templatePath = AppDomain.CurrentDomain.BaseDirectory + "Controllers\\" + templateFileName;
    var memoryStream = new MemoryStream();

    using (var fileStream = new FileStream(templatePath, FileMode.Open, FileAccess.Read))
        fileStream.CopyTo(memoryStream);

    using (var document = WordprocessingDocument.Open(memoryStream, true))
    {
        document.ChangeDocumentType(WordprocessingDocumentType.Document); // change from template to document

        var body = document.MainDocumentPart.Document.Body;

        //add some text 
        Paragraph paraHeader = body.AppendChild(new Paragraph());
        Run run = paraHeader.AppendChild(new Run());
        run.AppendChild(new Text("This is body text"));

        document.Close();
    }

    memoryStream.Position = 0; //let's rewind it
    return memoryStream;
}

Full test solution: https://github.com/sergeklokov/WordDocumentByOpenXML/blob/master/WordDocumentByOpenXML/Program.cs 完整的测试解决方案: https : //github.com/sergeklokov/WordDocumentByOpenXML/blob/master/WordDocumentByOpenXML/Program.cs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM