これがBlazorでファイルをアップロードする最良の方法ですか?

これがBlazorでファイルをアップロードする最良の方法ですか?

Blazorは本当に素晴らしいもので、開発効率を大幅に向上させます。多くのページインタラクション機能は、わずかなコードを書くだけで実現でき、しかもJavaScript不要で実現できます。Blazorでファイルアップロードがどれほど簡単か、あなたも決して想像したことがないでしょう!

最終更新 2022/03/16 7:36
懒得勤快
読了目安 3 分
カテゴリ
Blazor
タグ
.NET Blazor ファイルアップロード Blazor Server

Blazorは本当に素晴らしいもので、開発効率を大幅に向上させてくれます。多くのページインタラクション機能を、ほんのわずかなコードで実現できますし、しかもJavaScript不要です。Blazorを使ったファイルアップロードがどれほど簡単か、想像もつかなかったでしょう?

結論から言うと、Blazorで進捗表示付きのファイルアップロードを実装するのは本当に簡単です!効果は画像をご覧ください:

この小さな機能を実現するのに、わずか50行足らずのコードで済みました。それでは、ケーススタディを紹介します。

まず、Tewr.Blazor.FileReaderパッケージを導入します。このパッケージはファイルアップロードのストリーム読み取りを提供するため、サーバーサイドでアップロードされたファイルを読み込みながら書き込む操作が可能になります。

依存関係の注入を設定します(注:これはBlazor Serverモードです。WASM方式については文末のリポジトリドキュメントを参照してください):

services.AddFileReaderService();

次にページレイアウトを行います。とてもシンプルで、進捗表示と画像表示に使用する2つの変数を宣言します:

<input type="file" /><button>ファイルをアップロード</button>
<div>
  @if (!string.IsNullOrEmpty(_src)) {
  <img src="@_src" width="600px" />
  } else {
  <p>@progress</p>
  }
</div>

そしてコンポーネントにIFileReaderServiceサービスを注入します:

@using Tewr.Blazor.FileReader @inject IFileReaderService fileReaderService;

ファイル入力ボックスをC#コードとやり取りできるようにするため、ElementReferenceで参照します:

<input @ref="inputTypeFileElement" type="file" /><button>ファイルをアップロード</button>
<div>
  @if (!string.IsNullOrEmpty(_src)) {
  <img src="@_src" width="600px" />
  } else {
  <p>@progress</p>
  }
</div>
@code { private ElementReference inputTypeFileElement; private string _src;
private string progress; }

ボタンにイベントをバインドし、ボタンがトリガーされるとfileReaderServiceを介してファイルストリームを読み取ります。その後は通常のバイナリデータのコピー操作で、ファイルの転送進捗を取得し、計算してページに表示できます:

<button @onclick="ReadFile">ファイルをアップロード</button>
public async Task ReadFile()
{
    _src = "";
    foreach (var file in await fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync())
    {
        await using var fileStream = await file.OpenReadAsync();
        var buffer = new byte[2048];
        var finalBuffer = new byte[fileStream.Length];
        int count;
        int totalCount = 0;
        while ((count = await fileStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            Buffer.BlockCopy(buffer, 0, finalBuffer, totalCount, count);
            totalCount += count;
            progress = "ファイルアップロード中 " + (int)(totalCount * 100.0 / fileStream.Length) + "%";
            StateHasChanged();
        }
        _src = $"data:image/jpg;base64,{Convert.ToBase64String(finalBuffer)}";
        progress = "";
        StateHasChanged();
    }
}

完全なコードは以下の通りです:

@page "/counter" @using Tewr.Blazor.FileReader @inject IFileReaderService
fileReaderService;

<input @ref="inputTypeFileElement" type="file" />
<button @onclick="ReadFile">ファイルをアップロード</button>
<div>
  @if (!string.IsNullOrEmpty(_src)) {
  <img src="@_src" width="600px" />
  } else {
  <p>@progress</p>
  }
</div>

@code { private ElementReference inputTypeFileElement; private string _src;
private string progress; public async Task ReadFile() { _src = ""; foreach (var
file in await
fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync()) {
await using var fileStream = await file.OpenReadAsync(); var buffer = new
byte[2048]; var finalBuffer = new byte[fileStream.Length]; int count; int
totalCount = 0; while ((count = await fileStream.ReadAsync(buffer, 0,
buffer.Length)) != 0) { Buffer.BlockCopy(buffer, 0, finalBuffer, totalCount,
count); totalCount += count; progress = "ファイルアップロード中 " + (int)(totalCount * 100.0
/ fileStream.Length) + "%"; StateHasChanged(); } _src =
$"data:image/jpg;base64,{Convert.ToBase64String(finalBuffer)}"; progress = "";
StateHasChanged(); } } }

管理者の追記:

記事の先頭のデモ画像は1MB未満の画像を使用しています。Tewr.Blazor.FileReaderパッケージはファイルアップロードのストリーム読み取りを提供するため、大きなファイルのアップロードも可能です。以下は34.2MBのZIP圧縮ファイルをアップロードした例です(Blazor Serverモード):

デモは簡素で、gifではわかりにくいかもしれませんが、このパッケージが優れていることを示すためのものです。大きなファイルをアップロードするには、上記の1回の読み取りサイズを大きめに変更します。例:512KB:

var buffer = new byte[1024*512];

以下のMicrosoftのBlazorファイルアップロードドキュメントを見ると、1回のパケットサイズを20KBより大きくすると、ページが一瞬フリーズし、その後自動的にリフレッシュされてアップロード操作がリセットされる可能性があります。しかし、このパッケージを使用するとその問題は発生しません。このパッケージは非常に優れています。

以上で記事を終わります。

参考

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2021/12/10

(3/30)みんなで学ぶBlazor:Blazor ServerとBlazor WebAssemblyの違い

Visual Studioをダウンロードした後、まずBlazorソリューションを作成し、その中にBlazor Serverプロジェクトを構築します。ソリューションの場所は自分で選択できます(注:新しいバージョンのVisual Studioでは、Blazor ServerとBlazor WebAssemblyの新しいプロジェクトテンプレートが分割され、より直感的になっています)。

続きを読む
同じカテゴリ / 同じタグ 2024/02/29

Winformでもこんなデータ表示ができる

winform開発の過程で、データ表示機能が必要になることがよくあります。これまではgridcontrolコントロールを使用していましたが、今日は例を通して、winform blazor hybridでant design blazorのtableコンポーネントを使ってデータ表示を行う方法を紹介します。

続きを読む
同じカテゴリ / 同じタグ 2024/02/29

Winformの画面も綺麗にできる?

先日、winformでblazor hybridを使用することを紹介しました。また、blazorのUIを組み合わせることでwinformプログラムのデザインをより美しくできると言いました。今回はwinform blazor hybridで描画する例を挙げて説明します。参考になれば幸いです。

続きを読む