そのため、私たちの Web サイトには、Excel スプレッドシートとしてダウンロードできる複数のレポートがあります。ハードドライブから空白のテンプレート ファイルを読み込み、それを MemoryStream にコピーし、DocumentFormat.OpenXml.Spreadsheet を使用してデータをテンプレートにプッシュすることでこれを実現します。 ; 次に、ヘッダーを設定し、ストリームを Response にコピーする関数に MemoryStream を渡します。
FF と Chrome で素晴らしい動作をしますが、IE9 (および 8、私の QA によると) はリモート サーバーへのログインを求める Windows セキュリティ ログイン ダイアログをランダムに表示します。ダイアログをキャンセルするか、[OK] をクリックして (資格情報が無視されているようです)、期待どおりに Excel ファイルを取得できます。(CharlesProxy を使用して) クエリを確認すると、CharlesProxy を再度無効にするまでログイン ダイアログが表示されないため、開発マシンとサーバーの間のトラフィックに違いがあるかどうかを確認できません。また、開発/テストサーバーからだけで、ローカルホストからデバッグを実行しても発生しません。
問題のコードは次のとおりです。これはコード ビハインドのサーバー側関数から呼び出されるため、RespondAsExcel は応答をクリアし、代わりに xlsx を挿入します。
using (MemoryStream excelStream = new MemoryStream())
{
using (FileStream template = new FileStream(Server.MapPath(@"Reports\AlignedTemplateRII.xlsx"), FileMode.Open, FileAccess.Read))
{
Master.CopyStream(template, excelStream);
}
//Logic here to push data into the Memory stream using DocumentFormat.OpenXml.Spreadsheet;
Master.RespondAsExcel(excelStream, pgmName);
}
public void RespondAsExcel(MemoryStream excelStream, string fileName)
{
var contenttype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.Clear();
Response.ContentType = contenttype;
fileName = Utils.ReplaceWhiteSpaceWithUnderScores(fileName);
Response.AddHeader("content-disposition", "inline;filename=" + fileName);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite(excelStream.ToArray());
//If that doesn't work, can try this way:
//excelStream.WriteTo(Response.OutputStream);
Response.End();
}
public void CopyStream(Stream source, Stream destination)
{
byte[] buffer = new byte[32768];
int bytesRead;
do
{
bytesRead = source.Read(buffer, 0, buffer.Length);
destination.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}