Streaming In Memory Word Document using OpenXML SDK w/ASP.NET results in "corrupt" document
.net, asp.net, c#, ms-word, openxml
Solution
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.
Problem
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(); ```