I am unable to stream a word document that I create on the fly down to the browser. I am constantly getting a message from Microsoft Word that the document is corrupt.
When I run the code via a Console Application and take ASP.NET out of the picture, the document is generated correctly with no problems. I believe everything centers around writing the file down.
Here is my code:
using (MemoryStream mem = new MemoryStream())
{
// Create Document
using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true))
{
// Add a main document part.
MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
new Document(new Body()).Save(mainPart);
Body body = mainPart.Document.Body;
body.Append(new Paragraph(new Run(new Text("Hello World!"))));
mainPart.Document.Save();
// Stream it down to the browser
// THIS IS PROBABLY THE CRUX OF THE MATTER <---
Response.AppendHeader("Content-Disposition", "attachment;filename=HelloWorld.docx");
Response.ContentType = "application/vnd.ms-word.document";
mem.WriteTo(Response.OutputStream);
Response.End();
}
}
I have looked at a lot of links – but nothing quite works. I lot of people use MemoryStream.WriteTo
and some use BinaryWrite
– at this point I'm not sure what the correct way is. Also I've tried the longer content type, i.e. application/vnd.openxmlformats-officedocument.wordprocessingml.document
but no luck.
Some screenshots – even if you try to recover you get the same "parts are missing or invalid"
Solution for those who stumble on this question:
Within the using
directive of the WordProcessingDocument
, you must call:
wordDocument.Save();
Also to correctly stream the MemoryStream
, use this in the outer using block:
Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
Response.AppendHeader("Content-Disposition", "attachment;filename=HelloWorld.docx");
mem.Position = 0;
mem.CopyTo(Response.OutputStream);
Response.Flush();
Response.End();
Use CopyTo
instead, there is a bug in WriteTo
which makes it fail to write the entire content of the buffer when the target stream does not support writing everything in one go.
As variant for .NET Framework 3.5 and lower. This version of framework haven't method CopyTo
in class Stream
. Therefore, method WriteTo
is replaced by next code:
byte[] arr = documentStream.ToArray();
fileStream.Write(arr, 0, arr.Length);
Example was found by http://blogs.msdn.com/b/mcsuksoldev/archive/2010/04/09/creating-a-new-microsoft-word-document-from-a-template-using-openxml.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With