【问题标题】:Generating an excel file with EPPlus is failing使用 EPPlus 生成 excel 文件失败
【发布时间】:2012-03-25 09:33:18
【问题描述】:

当我尝试使用 EPPlus 生成 Excel 文件时,Excel 给我以下错误消息:

Excel 无法打开文件“myfilename.xlsx”,因为文件格式或文件扩展名无效。验证文件没有损坏,并且文件扩展名与文件格式匹配。

这是我的代码:

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

知道我做错了什么吗?

【问题讨论】:

  • 错误显示myfilename.xslx,而您的代码显示myfilename.xlsx。你真正使用的是哪一个?
  • 已回复yesterday。我认为这是同一个问题。
  • @M.Babcock - xlsx,这是一个错字。我将编辑问题。
  • 当我将流位置设置为 0 时,我发现此代码有效,并且我发现它比公认的解决方案更干净。

标签: c# asp.net-mvc excel epplus


【解决方案1】:

您需要做的就是重置流位置。 stream.Position = 0;

不应该直接写入响应,这不是 MVC 方式。它没有遵循正确的 MVC 管道,并且将控制器操作代码与 Response 对象紧密耦合。

当您在File() 中添加文件名作为第三个参数时,MVC 会自动添加正确的Content-Disposition 标头...因此您不需要手动添加它。

简而言之,这就是你想要的:

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

【讨论】:

  • 所以对此有疑问,我正在使用类似的方法,尽管我当前返回的是 FileStreamResponse 而不是文件对象。我遇到的问题是,如果用户在构建第一个文件时发出多个请求,它们似乎都被锁定并且 saveas 方法永远不会完成。您是否在使用 EPPlus 时遇到过这种情况?
  • 能贴出处理这个返回的ajax成功方法吗?
【解决方案2】:

您的代码没有显示stream 被写入HttpResponse - 大概是在您尚未发布的File 方法中完成的。

一种可行的方法如下:

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

【讨论】:

  • File 方法是ASP.Net MVC 的一部分。我会试试这个方法!
  • 奇怪,它现在显示“Excel 在 'myfilename.xlsx' 中发现了不可读的内容。您要恢复此工作簿的内容吗?如果您信任此工作簿的来源,请单击是。”如果我单击“是”,它似乎可以工作,但我不知道是什么导致了该错误。
  • 我之前看到过该错误消息,IIRC 它是在省略 Response.Clear() 时发生的。另一种可能性是 EPPlus 错误导致文件中的数据无效。您可以通过将文件保存在服务器上来测试它是什么,并查看在服务器上打开它时是否遇到相同的错误。
  • 另外,当使用File 方法时,您可能需要首先将 MemoryStream 定位到流的开头 (stream.Position = 0)。
  • 啊,“Excel 发现无法读取的内容”是我的错。我试图在第 0 列上设置宽度。
【解决方案3】:

和乔的回答类似,我还是要打电话给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();
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    相关资源
    最近更新 更多