ViewのデータをSubmitし、Contollerでビジネスロジックが走り(その中でダウンロードさせるファイル情報は取得・作成する)、Viewに戻ったあとに、ファイルダウンロード処理を走らせる。
単にファイルをダウンロードするだけではなく、Viewへほかの表示データなども戻す必要がある際に、ActionResultやFileStreamResultでは、両方を戻すことができない。
そのような時に、Controllerでは、Viewに戻すデータの作成、ダウンロードさせるファイルの作成を行うが、ContollerからViewに戻すのはファイル情報ではなく、Viewに戻すデータのみを戻す。
ダウンロードさせるファイルは、TempDataにbase64文字列として保持(Viewに戻れば破棄される)し、Viewの中で、ダウンロードとして処理させる。
Contoller側の処理:
public ActionResult Download()
{
var pdfSteam = XXXX;
using (var memoryStream = new MemoryStream())
{
pdfSteam.CopyTo(memoryStream);
//メモリーストリームからbase64文字列へ変換する
var b64String = Convert.ToBase64String(memoryStream.ToArray());
//画面でPDFのダウンロード処理ようにdata:application/pdf;base64,を付け、その後に、base64文字列と続ける
var dataUrl = "data:application/pdf;base64," + b64String;
TempData["dataUrl"] = dataUrl;
}
return RedirectToAction("index");
}
View側の処理:
@{
ViewBag.Title = "Test";
}
<h2>Test Download</h2>
<script>
@if (!string.IsNullOrEmpty(TempData["dataUrl"]?.ToString()))
{
//もしController側でdataUrlにデータを入れていた場合に、リンク(aタグ)を作成し、それをクリックすることで、base64文字列のデータをダウンロードさせる。
<text>
const link = document.createElement("a");
link.setAttribute("target", "_blank");
link.href = '@TempData["dataUrl"]';
link.download = "download";
link.click();
</text>
}
</script>
<form name="input" action="Download" method="post">......