简体   繁体   中英

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. I don't want to save this document on the file, and then read it as MemoryStream and return. Note: overload method WordprocessingDocument.CreateFromTemplate(template) do not have stream option vs WordprocessingDocument.Create(stream, ...)

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);

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).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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