Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

save the document created by docX into response and send it to user for downloading

Tags:

c#

c#-4.0

docx

I am trying to use the amazing DocX library on codeplex to create a word document.

when the user clicks a button, the document is created and I want to be able to send it to the user immediately via response.. I am doing something similar to this now:

Edited code based on suggestions

using (DocX Report = DocX.Create(string.Format("Report-{0}.doc", DateTime.Now.Ticks)))
{
    Paragraph p = Report.InsertParagraph();
    p.Append("Title").FontSize(30).Bold()
    .Append("Sub title").FontSize(28)
        .AppendLine()
        .Append(DateTime.Now.Date) 
    ;

    MemoryStream ms = new MemoryStream();
    Report.SaveAs(ms);


    Response.Clear();
    Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".docx\"");
    Response.ContentType = "application/msword";

    Response.Write(ms);
    Response.End();
}

I have tried a few variations of this.. but I am not able to achieve what I want.. Looking at this answer I can possibly save the document on the server and open with io stream.. but I want to avoid that extra step (and then I need to delete the file too)

I don't see the point of creating a file for few milli seconds.. there has to be a way to save the contents and send them to response stream.. right?

How'd I go about it? thanks..

EDIT: my current code either throws up cannot open file (Access denied) error If I am using file stream, OR downloads an empty document file without any content (sometimes, type of response is written to document)


This code gets me an MS word document with System.IO.MemoryStream as it's content..

Okay, here is the final working solution:

For some reason, DocX library doesn't want to save to Response.OutputStream directly, so I had to save it to memory stream and write the memory stream to response, like Neil & Daniel suggested. Here's what worked for me:

MemoryStream ms = new MemoryStream()
Report.SaveAs(ms);

Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".doc\");
Response.ContentType = "application/msword";

ms.WriteTo(Response.OutputStream);
Response.End();
like image 683
LocustHorde Avatar asked Jan 24 '12 14:01

LocustHorde


People also ask

What does export to DOCX mean?

Put simply, . Doc is the older version of a Microsoft Word Document. DocX is the newer version, form versions of Microsoft Word 2007 onwards. Now before you jump in thinking that the added X makes the document extreme or better in some way, that X on the end just stands for 'Office Open XML'.

How is a DOCX File created?

To create a DOCX template from Workspace ExplorerAt the top of the Workspace Explorer, click New Template. From the Type drop down, select DOCX Template (. docx). Type a File Name and a Title (optionally, also a Description).


2 Answers

This might be a bit late, but I found a way to get this working with FileStreamResult:

    public FileStreamResult DownloadDocument()
    {
        using (DocX document = DocX.Create(@"Test.docx"))
        {
            // Insert a new Paragraphs.
            Paragraph p = document.InsertParagraph();

            p.Append("I am ").Append("bold").Bold()
            .Append(" and I am ")
            .Append("italic").Italic().Append(".")
            .AppendLine("I am ")
            .Append("Arial Black")
            .Font(new FontFamily("Arial Black"))
            .Append(" and I am not.")
            .AppendLine("I am ")
            .Append("BLUE").Color(Color.Blue)
            .Append(" and I am")
            .Append("Red").Color(Color.Red).Append(".");

            var ms = new MemoryStream();
            document.SaveAs(ms);
            ms.Position = 0;

            var file = new FileStreamResult(ms, "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
            {
                FileDownloadName = string.Format("test_{0}.docx", DateTime.Now.ToString("ddMMyyyyHHmmss"))
            };

            return file;

        }
    }

The important bit is setting the Position of the memorystream back to 0, otherwise it appeared to be at the end, and the file was returning empty.

like image 116
Chris W Avatar answered Oct 03 '22 02:10

Chris W


Try using a MemoryStream instead of a FileStream.

Your current code looks really wrong:

You are saving the report to the OutputStream of the current response and then clear that response (!)

like image 30
Daniel Hilgarth Avatar answered Oct 03 '22 01:10

Daniel Hilgarth