web-dev-qa-db-ja.com

応答に.XLSXを出力するときのEPPlusエラー

ここで、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保存する原因となる可能性があるものがありますか?

16
j00b

私はこの問題の解決策を見つけました!ローカルに保存したときにファイルを開くことができましたが、応答を介してではなかったため、予想どおり、応答と関係がありました。

ここでの問題は、例外がログに記録されて表示されていた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
    }
}
17
j00b

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

8
yedevtxt

IEからEPPlusを開くことができませんでした。正常に保存され、エラーなしで開きました。 (Chromeは保存とオープンの両方で正常に機能しました)。ここでの提案は私にはうまくいきませんでした-私が最終​​的に私のために働いたashxファイルではなく、aspxファイルを使用していたためかもしれません。

何時間も検索した後、私は このstackoverflow post のようにashxファイルを使用することになり、EPPlusを使用して警告/破損したファイルメッセージなしですべてのブラウザで動作するようになりました。

他の人を助けるかもしれない追加のリソース:

これで他の誰かの時間を節約できることを願っています。

0
John

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

WriteToメソッドの代わりに、次のことを試してください。

context.Response.BinaryWrite(package.GetAsByteArray());
0
JustinStolle