сохранить созданный docX документ в ответ и отправить его пользователю для скачивания - PullRequest
8 голосов
/ 24 января 2012

Я пытаюсь использовать удивительную библиотеку DocX на codeplex для создания текстового документа.

, когда пользователь нажимает кнопку, документ создается, и я хочу иметь возможностьотправить его пользователю немедленно через ответ .. Я делаю что-то похожее на это сейчас:

Отредактированный код на основе предложений

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

Я пробовал нескольковарианты этого .. но я не могу достичь того, что я хочу .. Глядя на этот ответ Возможно, я могу сохранить документ на сервере и открыть с потоком IO ... но я хочу избежать этогошаг (а потом мне тоже нужно удалить файл)

Не вижу смысла создавать файл за несколько миллисекунд ... должен быть способ сохранить содержимое и отправить его в ответстрим .. правильно?

Как бы я поступил?спасибо ..

РЕДАКТИРОВАТЬ: мой текущий код либо выдает не удается открыть файл ошибка (доступ запрещен) Если я использую поток файлов, ИЛИ загружает пустой файл документа без какого-либо содержимого (иногда, тип ответа записывается вдокумент)


Этот код дает мне документ MS Word с System.IO.MemoryStream в качестве его содержимого.

Хорошо, вот окончательное рабочее решение:

По какой-то причине библиотека DocX не хочет сохранять в Response.OutputStream напрямую, поэтому мне пришлось сохранить ее в потоке памяти и записать поток памяти в ответ, например Neil & Daniel предложено.Вот что сработало для меня:

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

Ответы [ 4 ]

5 голосов
/ 21 апреля 2013

Это может быть немного поздно, но я нашел способ заставить это работать с 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;

        }
    }

Важным битом является установка позиции потока памяти обратно в 0, в противном случае он выглядел какв конце файл возвращался пустым.

2 голосов
/ 24 января 2012

Когда вы делаете Report.SaveAs(response.OutputStream); - он уже записывает содержимое файла в выходной поток. Вам не нужно делать Response.Write(response.OutputStream);

Итак, ваш код должен выглядеть так:

...

Report.SaveAs(response.OutputStream);
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".doc\"");
Response.ContentType = "application/msword";
2 голосов
/ 24 января 2012

Попробуйте использовать MemoryStream вместо FileStream.

Ваш текущий код выглядит действительно неправильно:

Вы сохраняете отчет в OutputStream текущего ответа итогда очистите этот ответ (!)

1 голос
/ 24 января 2012

Я думаю, у вас есть вещи немного впереди и в замешательстве.

Сначала очистите вывод, затем добавьте заголовки, затем запишите содержимое.

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

// This writes the document to the output stream.
Report.SaveAs(response.OutputStream); 

Response.End(); 

Кроме того, если ваш файл представляет собой файл формата docx, добавьте .docx, а не .doc к вашему имени файла.

...