ここで、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で読み取り不可能なコンテンツを検出しました。このワークブックの内容を復元しますか?このワークブックのソースを信頼する場合は、[はい]をクリックしてください
[はい]をクリックすると、次のプロンプトが表示されます。
このファイルは、MicrosoftExcelを使用して開くことはできません。 Microsoft Office Online Webサイトで、ファイルを開くことができるコンバーターを検索しますか?
ここでNo
を選択すると、Excelファイルが開き、次のエラーが表示されます。
Excelはファイルレベルの検証と修復を完了しました。このワークブックの一部は、修復または破棄されている可能性があります。
[〜#〜] but [〜#〜]ファイルは正常に読み込まれ、正しくフォーマットされているように見えます。しかし、ファイルを開こうとするたびに、同じプロンプトとエラーメッセージが表示されます。
注:データを出力するコードは、これらのシナリオのいずれでも変更されません。
誰かがこのようなものを見たことがありますか?または、応答に出力するときに、これがファイルを誤ってonly保存する原因となる可能性があるものがありますか?
私はこの問題の解決策を見つけました!ローカルに保存したときにファイルを開くことができましたが、応答を介してではなかったため、予想どおり、応答と関係がありました。
ここでの問題は、例外がログに記録されて表示されていた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
}
}
joobに感謝します。あなたのリンクは、「GetAsByteArray()」を呼び出すという私の問題を解決しました。以下にリストされているように、そしてあなたが与えたリンクで、私は例外が追加されるのを防ぎます。いくつかの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
IEからEPPlusを開くことができませんでした。正常に保存され、エラーなしで開きました。 (Chromeは保存とオープンの両方で正常に機能しました)。ここでの提案は私にはうまくいきませんでした-私が最終的に私のために働いたashxファイルではなく、aspxファイルを使用していたためかもしれません。
何時間も検索した後、私は このstackoverflow post のようにashxファイルを使用することになり、EPPlusを使用して警告/破損したファイルメッセージなしですべてのブラウザで動作するようになりました。
他の人を助けるかもしれない追加のリソース:
これで他の誰かの時間を節約できることを願っています。
Excelにエクスポートするためにボタンをクリックしたときの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;
}
}
WriteTo
メソッドの代わりに、次のことを試してください。
context.Response.BinaryWrite(package.GetAsByteArray());