2012-03-07 110 views
13

當我嘗試使用產生的EPPlus Excel文件的文件時,Excel給我下面的錯誤信息:生成一個Excel與EPPlus失敗

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

任何想法,我做錯了嗎?

+0

錯誤說'myfilename.xslx'而你的代碼顯示'myfilename.xlsx'。你真的在使用哪一個? – 2012-03-07 20:29:32

+0

已回答[昨天](http://stackoverflow.com/a/9574414/284240)。我認爲這是同樣的問題。 – 2012-03-07 20:44:29

+0

@ M.Babcock - xlsx,這是一個錯字。我將編輯該問題。 – 2012-03-07 20:56:41

回答

27

所有你需要做的就是重置流位置。 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); 
    } 
} 
+0

所以關於這個問題,我正在使用類似的方法,雖然我目前正在返回一個FileStreamResponse而不是一個文件對象。但我遇到的問題是,如果用戶在構建第一個文件時發出多個請求,則它們似乎都被鎖定,saveas方法從未完成。您是否遇到過EPPlus? – Shawn 2014-02-11 02:39:47

10

您的代碼未顯示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(); 
+0

'File'方法是'ASP.Net MVC'的一部分。我會嘗試這種方式! – 2012-03-07 20:52:41

+0

奇怪的是,它現在說「Excel在'myfilename.xlsx'中發現了不可讀的內容。是否要恢復此工作簿的內容?如果您信任此工作簿的源,請單擊」是「。如果我點擊是,它似乎工作,但我不知道是什麼給這個錯誤。 – 2012-03-07 20:59:10

+0

我之前看到過這個錯誤信息,IIRC它在Response.Clear()被省略時發生了。另一種可能性是EPPlus錯誤導致文件中的數據無效。您可以通過將文件保存在服務器上來測試它是哪一個,並查看在服務器上打開時是否出現相同的錯誤。 – Joe 2012-03-07 21:31:40

2

喬的回答相似的,我還是不得不打電話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(); 
    }