Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# return memory stream from OpenXML resulting to a corrupted word file

I have a problem with a MemoryStream from OpenXML. I succeed with opening a Word file, changing it and downloading it through the HttpResponse if I do all the steps in a single method.

But if I try to do it in two different classes (or methods) by returning the MemoryStream, I get a corrupted word file. I thought about a flushing or buffer problem but I don't find a solution.

Here is the working code :

    public void FillTemplateOpenXmlWord(HttpResponse response)
    {
        string filePath = @"c:\template.docx";
        byte[] filebytes = File.ReadAllBytes(filePath);

        using (MemoryStream stream = new MemoryStream(filebytes))
        {
            using (WordprocessingDocument myDoc = WordprocessingDocument.Open(stream, true))
            {
                // do some changes
                ...
                myDoc.MainDocumentPart.Document.Save();
            }

            string docx = "docx";
            response.Clear();
            response.ClearHeaders();
            response.ClearContent();
            response.AddHeader("content-disposition", "attachment; filename=\"" + docx + ".docx\"");
            response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            response.ContentEncoding = Encoding.GetEncoding("ISO-8859-1");
            stream.Position = 0;
            stream.CopyTo(response.OutputStream);
            response.End();
        }
    }

Here is the non-working code :

    public void OpenFile(HttpResponse response)
    {
        MemoryStream stream = this.FillTemplateOpenXmlWord();

        string docx = "docx";
        response.Clear();
        response.ClearHeaders();
        response.ClearContent();
        response.AddHeader("content-disposition", "attachment; filename=\"" + docx + ".docx\"");
        response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        response.ContentEncoding = Encoding.GetEncoding("ISO-8859-1");
        stream.Position = 0;
        stream.CopyTo(response.OutputStream);
        response.End();
    }

    public MemoryStream FillTemplateOpenXmlWord()
    {
        string filePath = @"c:\template.docx";
        byte[] filebytes = File.ReadAllBytes(filePath);

        using (MemoryStream stream = new MemoryStream(filebytes))
        {
            using (WordprocessingDocument myDoc = WordprocessingDocument.Open(stream, true))
            {
                // do some changes
                ...
                myDoc.MainDocumentPart.Document.Save();
            }

            return stream;
        }
    }

Any idea ?

thank you

like image 959
DotNetBeliever Avatar asked Jan 21 '14 10:01

DotNetBeliever


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.

What is C full form?

Full form of C is “COMPILE”.

Is C programming hard?

C is more difficult to learn than JavaScript, but it's a valuable skill to have because most programming languages are actually implemented in C. This is because C is a “machine-level” language. So learning it will teach you how a computer works and will actually make learning new languages in the future easier.


1 Answers

Here's what I'm using for generating OpenXML files from memory stream. In this case it makes XLSX file from template on server, but it should be similar for other OpenXml formats.

Controller action:

public class ExportController : Controller
{
    public FileResult Project(int id)
    {
        var model = SomeDateModel.Load(id); 
        ProjectExport export = new ProjectExport();
        var excelBytes = export.Export(model);
        FileResult fr = new FileContentResult(excelBytes, "application/vnd.ms-excel")
        {
            FileDownloadName = string.Format("Export_{0}_{1}.xlsx", DateTime.Now.ToString("yyMMdd"), model.Name)
        };

        return fr;
    }
}

// Helper class

public class ProjectExport
{
    private WorkbookPart workbook;
    private Worksheet ws;

    public byte[] Export(SomeDateModel model)
    {
        var template = new FileInfo(HostingEnvironment.MapPath(@"~\Export\myTemplate.xlsx"));
        byte[] templateBytes = File.ReadAllBytes(template.FullName);

        using (var templateStream = new MemoryStream())
        {
            templateStream.Write(templateBytes, 0, templateBytes.Length);
            using (var excelDoc = SpreadsheetDocument.Open(templateStream, true))
            {
                workbook = excelDoc.WorkbookPart;
                var sheet = workbook.Workbook.Descendants<Sheet>().First();

                ws = ((WorksheetPart)workbook.GetPartById(sheet.Id)).Worksheet;

                sheet.Name = model.Name;
                // Here write some other stuff for setting values in cells etc...
            }
            templateStream.Position = 0;
            var result = templateStream.ToArray();
            templateStream.Flush();

            return result;
        }
    }
like image 106
Tomino Avatar answered Oct 02 '22 12:10

Tomino