views:

1043

answers:

1

I'm working on some code that generates an Excel spreadsheet server-side and then downloads it to the user. I'm using ExcelPackage to generate the file.

The generation is working just fine. I can open the generated files using Excel 2007 with no issues. But, I'm having trouble downloading the file with Response.TransmitFile().

Right now, I have the following code:

//Generate the file using ExcelPackage
string fileName = generateExcelFile(dataList, "MyReportData");

Response.AddHeader("content-disposition", "attachment;filename=FileName.xls");
Response.ContentType = "application/vnd.xls"
Response.Charset = "";
Response.TransmitFile(fileName);

When Excel 2007 opens the file downloaded as above, it gives the "file format doesn't match extension" warning. After clicking past the warning, Excel displays the raw xml contents of the file.

If I change the file extension, like so

Response.AddHeader("content-disposition", "attachment;filename=FileName.xlsx");

Excel 2007 gives an "Excel found unreadable content in the file" error, followed by a dialog that offers to locate a converter on the web. If I click "no" on this dialog, Excel is able to load the data.

I've also experimented with different MIME types, like application/vnd.ms-excel and application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, combined with file extensions of .xls and .xlsx. All combinations result in one of the two behaviors mentioned above.

What is the correct combination of file extension and MIME type to use in this scenario? What else could cause this failure, other than an improper MIME type or extension?

FYI, this is occurring with Visual Studio's built-in development web server. I haven't yet tried this with IIS.

+3  A: 

I can't definitely say that there's anything wrong with your approach, but I'll just share some observations from doing something similar.

Headers are Pascal Case, most browsers shouldn't care but I would change your content-disposition to Content-Disposition. Changing the Charset shouldn't be necessary or relevant. Your content type should be fine, I would only use application/vnd.openxmlformats-officedocument.spreadsheetml.sheet and .xlsx if that is actually the content of the file, otherwise stick with application/vnd.ms-excel and .xls.

Another thing you should consider is sending the browser the Content-Length:

Response.AddHeader("Content-Length", new System.IO.FileInfo("FileName.xlsx").Length);

Also have you tried this with multiple browsers? Just wondering if it's a vendor-specific problem.

As a last ditch effort, you can set your Content-Type to application/octet-stream, and any browser should offer to download it, and then most browsers will let you open it after it's downloaded based on the extension.

Brad
Setting the Content-Length header did the trick. Alternately, calling Response.End() after TransmitFile() also worked. So, I guess the browser didn't know where the end of the response was?
Odrade
Without setting the Content-Length header or calling Response.End(), the browser definitely misinterprets the file size and saves too much data to the file. Thanks for the help!
Odrade
Content-Length is definitely the way to go here. I found some useful info on Response.End() on Rick Strahl's blog that should be shared with future visitors of this page: http://west-wind.com/weblog/posts/368975.aspx
Odrade
Awesome! Glad you got it worked out.
Brad