我在这里使用EPPlus创建一些.XLSX文件有一个奇怪的问题。我正在创建一个包,然后输出到响应。
我创建了一个包,如下所示:
var file = new FileInfo(@"C:\Test.xlsx");
ExcelPackage package = new ExcelPackage(file);
//...code to output data...//
package.Save();
这会将文件正确保存到我的本地C:驱动器,当我打开它时效果很好。没有错误或任何东西,格式是正确的等等。
但是,我现在希望将此文件输出到响应流,所以我修改了代码,我必须看起来像这样:
ExcelPackage package = new ExcelPackage();
//...code to output data...//
MemoryStream result = new MemoryStream();
package.SaveAs(result);
context.Response.Clear();
context.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
context.Response.AddHeader("Content-Disposition", "attachment;filename=MissionDetails.xlsx");
result.WriteTo(context.Response.OutputStream);
context.Response.End();
但是当我运行此代码时,我在尝试打开Excel文件时收到以下提示:
Excel在filename.xlsx中找到了不可读的内容。你想恢复这个工作簿的内容吗?如果您信任此工作簿的来源,请单击是
单击是然后显示以下提示:
使用Microsoft Excel无法打开此文件。是否要在Microsoft Office Online网站上搜索可以打开文件的转换器?
我在这里选择No
,然后打开Excel文件并显示以下错误:
Excel完成了文件级验证和修复。本工作簿的某些部分可能已被修复或丢弃。
但该文件然后加载正常,似乎格式正确和一切。但每次我尝试打开文件时,它都会提供相同的提示和错误消息。
注意:输出数据的代码在以下任何一种情况下都不会改变。
有没有人见过这样的东西?或者在输出到响应时知道是什么原因导致文件错误地 ?
答案 0 :(得分:14)
我找到了解决这个问题的方法!正如预期的那样,它确实与响应有关,因为我能够在本地保存时打开文件,但不是通过响应。
这里的问题是我的代码被包装在 try..catch 块中,其中记录并显示了异常。
我注意到,当您调用 Response.End()时,会引发 System.Threading.ThreadAbortException 。当引发此错误时,似乎错误的输出被附加到我的文件的末尾。
当我摆脱针对该特定异常的错误记录时,它工作得很好!
请参阅此帖子了解更多信息http://epplus.codeplex.com/discussions/223843?ProjectName=epplus
//...output code...//
catch(Exception ex){
if (!(ex is System.Threading.ThreadAbortException))
{
//Log other errors here
}
}
答案 1 :(得分:8)
感谢joob你的链接soved我的问题是它调用“GetAsByteArray()”。如下所示,并在您给出的链接中,我gess保持不附加异常。一些majic。
你得到了投票!
mrxrsd
Editor
Aug 17, 2010 at 12:30 PM
Call response.clear before send stream back to client.
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=file.xlsx");
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.BinaryWrite(pck.GetAsByteArray());
Response.End();
http://epplus.codeplex.com/discussions/223843?ProjectName=epplus
答案 2 :(得分:0)
代替WriteTo
方法,试试这个:
context.Response.BinaryWrite(package.GetAsByteArray());
答案 3 :(得分:0)
page.aspx.cs代码
string templateFileName = Server.MapPath("~/ReportingTemplate/test.xlsx");
System.IO.FileInfo templateFile = new System.IO.FileInfo(templateFileName);
String message = ExcelPackagePlusLibrary.EPPlus.ExportToExcel(templateFile, dt, false, exportFileName, Response, "Data", "Summary", "Please type the client name here");
if (String.IsNullOrEmpty(message) == false)
{
/* Exception occur. */
}
dt.Clear();
///////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// ExportToExcel is a method used for Export To Excel with template file.
///
/// </summary>
/// <param name="templateFile">The fully qualified name of the new file, or the relative file name. Do not end the path with the directory separator character.</param>
/// <param name="dt">Datatable for export.</param>
/// <param name="printHeaders">Datatable's header used or not, when Export it. </param>
/// <param name="exportFileName">provide fileName only not path. </param>
/// <param name="Response">System.Web.HttpResponse. </param>
/// <param name="sheetNames">arg[0] means provide sheet name where you want to load data. \n (Optional Parameter) arg[1] means provide sheet name where you want to edit. (Optional Parameter) arg[2] means if your intention is to Edit sheet so provide searchText.</param>
///
public static string ExportToExcel(FileInfo templateFile, DataTable dt, bool printHeaders, string exportFileName, System.Web.HttpResponse Response, params String[] sheetNames)
{
try
{
using (ExcelPackage p = new ExcelPackage(templateFile, false))
{
EPPlus.AddSheetWithTemplate(p, dt, sheetNames[0], printHeaders);
String[] clientName = exportFileName.Split(new char[] { '_' }, 2);
if (sheetNames.Count() > 2)
{
ExcelPackagePlusLibrary.EPPlus.EditSheet(p, sheetNames[1], sheetNames[2], clientName[0] ?? exportFileName);
}
Byte[] fileBytes = p.GetAsByteArray(); //Read the Excel file in a byte array
//Clear the response
Response.ClearHeaders();
Response.ClearContent();
Response.Clear();
//Response.Cookies.Clear();
//Add the header & other information
//Response.Cache.SetCacheability(System.Web.HttpCacheability.Private);
//Response.CacheControl = "private";
//Response.Charset = System.Text.UTF8Encoding.UTF8.WebName;
//Response.ContentEncoding = System.Text.UTF8Encoding.UTF8;
//Response.AppendHeader("Content-Length", fileBytes.Length.ToString());
//Response.AppendHeader("Pragma", "cache");
//Response.AppendHeader("Expires", "60");
Response.AddHeader("Content-Disposition",
"attachment; " +
"filename=" + exportFileName + "; " +
"size=" + fileBytes.Length.ToString() + "; " +
"creation-date=" + DateTime.Now.ToString("R").Replace(",", "") + "; " +
"modification-date=" + DateTime.Now.ToString("R").Replace(",", "") + "; " +
"read-date=" + DateTime.Now.ToString("R").Replace(",", ""));
//Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.ContentType = "application/x-msexcel";
//Write it back to the client
Response.BinaryWrite(fileBytes);
Response.Flush();
Response.Close();
/* Download to Client Side. */
//DirectoryInfo dir = new DirectoryInfo(Server.MapPath("~/Testing/Downloaded/" + DateTime.Now.ToString("MM-dd-yyyy")));
//if (!dir.Exists)
//{
// dir.Create();
//}
//File.WriteAllBytes(dir.FullName + "\\" + fileName, fileBytes);
return String.Empty;
}
}
catch (Exception ex)
{
_ErrorMessage = ex.Message.ToString();
return _ErrorMessage;
}
}
答案 4 :(得分:0)
我无法从IE打开EPPlus,它保存得很好并且没有错误地打开。 (chrome对于保存和打开都工作正常)。这里的建议对我没有用 - 可能是因为我使用的是aspx文件,而不是最终为我工作的ashx文件。
经过几个小时的搜索后,我最终按照this stackoverflow post使用了ashx文件,现在我在所有浏览器中都可以使用它,而不使用EPPlus发出警告/ corupt文件消息。
可能有助于他人的其他资源:
我希望这能节省一些时间。