Generating an excel file with EPPlus is failing
Solution 1
All you need to do is reset the stream position. stream.Position = 0;
You shouldn't write directly to the Response, it's not the MVC way. It doesn't follow the correct MVC pipeline and it tightly couples your controller action code to the Response object.
When you add a file name as the 3rd parameter in File()
, MVC automatically adds the correct Content-Disposition
header... so you shouldn't need to add it manually.
The short of it is, this is what you want:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
return File(stream, contentType, fileName);
}
}
Solution 2
Your code doesn't show stream
being written to the HttpResponse
- presumably being done in the File
method which you haven't posted.
One way that does work is the following:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader(
"content-disposition", String.Format(CultureInfo.InvariantCulture, "attachment; filename={0}", fileName));
Response.BinaryWrite(package.GetAsByteArray());
Response.End();
Solution 3
Similar to Joe's answer, I still had to call Response.ClearHeaders()
:
protected void btnDownload_Click(object sender, EventArgs e)
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample2");
ws.Cells["A1"].Value = "Sample 2";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 2 outputs the sheet using the Response.BinaryWrite method";
Response.Clear();
Response.ClearHeaders();
Response.BinaryWrite(pck.GetAsByteArray());
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Sample2.xlsx");
Response.End();
}
Matt Grande
Matt Grande is a software developer from Hamilton, ON. He works in C# and Ruby on Rails. He is overweight and has bad hair.
Updated on February 11, 2020Comments
-
Matt Grande over 4 years
When I try to generate an Excel file using EPPlus, Excel give me the following error message:
Excel cannot open the file 'myfilename.xlsx' because the file format or file extension is not valid. Verify the the file has not been corrupted and that the file extension matches the format of the file.
Here's my code:
public ActionResult Index() { using (ExcelPackage package = new ExcelPackage()) { // I populate the worksheet here. I'm 90% sure this is fine // because the stream file size changes based on what I pass to it. var stream = new MemoryStream(); package.SaveAs(stream); string fileName = "myfilename.xlsx"; string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; var cd = new System.Net.Mime.ContentDisposition { Inline = false, FileName = fileName }; Response.AppendHeader("Content-Disposition", cd.ToString()); return File(stream, contentType, fileName); } }
Any idea what I'm doing wrong?
-
Matt Grande about 12 yearsThe
File
method is part ofASP.Net MVC
. I'll try this way! -
Matt Grande about 12 yearsStrange, it now says "Excel found unreadable content in 'myfilename.xlsx'. Do you want to recover the contents of this workbook? If you trust the source of this workbook, click Yes." If I click Yes, it seems to work, but I have no idea what's giving that error.
-
Joe about 12 yearsI have seen that error message before, IIRC it happened when Response.Clear() was omitted. Another possibility is that an EPPlus bug results in invalid data in the file. You can test which it is by saving the file on the server, and seeing if you get the same error when opening it on the server.
-
Joe about 12 yearsAlso when using the
File
method, you may need to first position your MemoryStream to the start of the stream (stream.Position = 0
). -
Matt Grande about 12 yearsAhh, the "Excel found unreadable content" was my fault. I was trying to set a width on Column 0.
-
Charlino over 11 years-1 this isn't the way you should do it... it's not the MVC way and it tightly couples your code to the response object. All you need to do is reset the stream position.
-
Shawn over 10 yearsSo question about this, I am using a similar method although I am currently returning a FileStreamResponse instead of a file object. The problem I am running into though is that if the user makes more than one request while the first file is being build, they all seem to get locked up and the saveas method never completes. Have you ran into this with EPPlus?
-
Christian Doulos about 3 yearsCan yo post the ajax success method that handles this return?