blazorでファイルダウンロード

blazorにはwebappのFileResultを使用したPostBackような動的にファイルコンテンツを作成して、ファイルをダウンロードさせる仕組みが無い。

では、どうやってファイルコンテンツを作成して、ダウンロードさせるかを調べてみた。

普通に考えると、1番簡単なのは、コールバックでコンテンツを作成して、Data URLに変換し、そのリンクを表示させる方法だが、これだと、作成のトリガーとリンクをクリックするという、2アクションが必要になる。

結局、作成トリガー(例えばボタンクリック)でファイルのダウンロードまで、行うには、Javascriptの助けを借りることになる。

以下のような感じで可能だが、サイズ制限(MSのサイトでは250Mbytes以下と記述されていた)があるようだ。

//
//  ファイルをダウンロードするJSヘルパー
//      やっていることは単純で、StreamからBlobを作成してそのurlをもった、
//      aタグを生成し、aタグに対してclickイベントを発生させた後、aタグとdata url
//      に割いているリソースを開放。
//      結構良く使う手段だね。blazor独自の点は.NETのStreamを
//      Javascript用にWrappingしてarrayBufferを取得している点ぐらい。
var mylibrary = {
    DownloadFile : async (StreamRef, FileName) => {
        const arrayBuffer = await StreamRef.arrayBuffer();
        const blob = new Blob([arrayBuffer]);
        const url = URL.createObjectURL(blob);
        const anchorElement = document.createElement('a');
        anchorElement.href = url;
        anchorElement.download = FileName ?? '';
        anchorElement.click();
        anchorElement.remove();
        URL.revokeObjectURL(url);
    }
};
using(MemoryStream mstm = new MemoryStream()) {
	// コンテンツ作成
	await mstm.FlushAsync();
	// 念のため
	mstm.Seek(0L,SeekOrigin.Begin);
	// Javascriptに渡すためのStreamリファレンス作成
	using var stmRef = new DotNetStreamReference(stream: mstm);
	// Javascript呼出
	await JSRuntime.InvokeVoidAsync("mylibrary.DownloadFile",stmRef,FileName);
}

大きいファイルの場合は、物理的にファイルを作成して、そのリンクでaタグ作成および、クリック・・・という形を取れとのこと。

何か他に良い方法は無いものだろうか・・・

ファイルダウンロードの標準的な仕組みをblazor内で定義して欲しいものだ。

takezou について

ソフトウェア開発会社(ITと言う言葉は大嫌い)で働く、元技術者。 未だに、社内システム位は作ってますが・・・ プログラミング言語はC#が好き。 好きなことだけ拾って投稿しているので、内容にはあまり期待しないでねw
カテゴリー: .NET, asp.net core, Blazor, C#, javascript, Web, 技術系 パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください