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.