使用Response.TransmitFile()下载.xlsx文件

15

我正在开发一些生成Excel电子表格并在服务器端下载到用户的代码。我正在使用ExcelPackage生成文件。

生成过程很顺利。我可以使用Excel 2007打开生成的文件,没有任何问题。但是,我在使用Response.TransmitFile()下载文件时遇到了麻烦。

现在,我有以下代码:

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

当Excel 2007打开上述下载的文件时,它会发出“文件格式与扩展名不匹配”的警告。 单击警告后,Excel会显示文件的原始XML内容。

如果我更改文件扩展名,就像这样

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

在Excel 2007中,会出现“Excel在文件中发现不可读内容”的错误,随后会出现一个对话框,询问是否在网上查找转换器。如果我在此对话框上单击“否”,Excel是能够加载数据的。

我还尝试了不同的MIME类型,例如application/vnd.ms-excelapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet,结合.xls和.xlsx文件扩展名的各种组合方式。所有组合方式都会导致上述两种行为之一。

在这种情况下,正确的文件扩展名和MIME类型组合方式是什么?除了不正确的MIME类型或扩展名之外,还有什么可能导致这种失败?

顺便说一句,这是在Visual Studio内置的开发Web服务器中发生的。我还没有尝试在IIS中进行此操作。

3个回答

18

我无法确定你的方法有什么问题,但是我会分享一些类似操作的观察结果。

标头应该使用帕斯卡大小写,大多数浏览器不应该有问题,但我会将content-disposition更改为Content-Disposition。更改字符集可能并不必要或相关。您的内容类型应该没问题,如果文件实际上是application/vnd.openxmlformats-officedocument.spreadsheetml.sheet和.xlsx,则只需使用它们,否则请使用application/vnd.ms-excel和.xls。

另一个需要考虑的事情是向浏览器发送Content-Length:

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

您是否尝试在多个浏览器中使用此功能?我想知道这是否是供应商特定问题。

作为最后的努力,您可以将Content-Type设置为application/octet-stream,任何浏览器都应该提供下载选项,下载后,大多数浏览器将根据扩展名允许您打开该文件。


2
设置Content-Length头部就可以了。或者,在TransmitFile()之后调用Response.End()也可以。所以,我猜测浏览器不知道响应的结尾在哪里? - Odrade
没有设置Content-Length标头或调用Response.End(),浏览器肯定会错误解释文件大小,并将太多数据保存到文件中。谢谢帮助! - Odrade
Content-Length在这里绝对是最好的选择。我在Rick Strahl的博客上找到了一些关于Response.End()的有用信息,应该与未来访问者分享:http://west-wind.com/weblog/posts/368975.aspx - Odrade

3

使用这个

HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=\"filename + ".zip" + "\"");
                Response.TransmitFile(zipPath);
                Response.Flush();
                Response.Close();
                Response.End();

在你的代码中是

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

0

试试这样

public void DataTableToExcel(DataTable dt, string Filename)
{
    MemoryStream ms = DataTableToExcelXlsx(dt, "Sheet1");
    ms.WriteTo(HttpContext.Current.Response.OutputStream);
    HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + Filename);
    HttpContext.Current.Response.StatusCode = 200;
    HttpContext.Current.Response.End();
}

public static MemoryStream DataTableToExcelXlsx(DataTable table, string sheetName)
{
    MemoryStream result = new MemoryStream();
    ExcelPackage excelpack = new ExcelPackage();
    ExcelWorksheet worksheet = excelpack.Workbook.Worksheets.Add(sheetName);
    int col = 1;
    int row = 1;
    foreach (DataColumn column in table.Columns)
    {
        worksheet.Cells[row, col].Value = column.ColumnName.ToString();
        col++;
    }
    col = 1;
    row = 2;
    foreach (DataRow rw in table.Rows)
    {
        foreach (DataColumn cl in table.Columns)
        {
            if (rw[cl.ColumnName] != DBNull.Value)
                worksheet.Cells[row, col].Value = rw[cl.ColumnName].ToString();
            col++;
        }
        row++;
        col = 1;
    }
    excelpack.SaveAs(result);
    return result;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接