Blazorで画像を選択して表示する

はじめに

選択した画像ファイルをアプリ上で表示する機能をBlazorで実装したいと思い調べていたのですが、少し苦労したことがあったので共有します。

環境

Blazor Server (.NET 6)
Microsoft Visual Studio Professional 2022 (64-bit) 17.2.5

実装手順

実装する方法は以下のドキュメントにある通りです。

docs.microsoft.com

ここでは主にコードを抜粋します。

まずはPages/_Layout.cshtmlのbodyタグ内に以下を記述します。

<script>
  window.setImage = async (imageElementId, imageStream) => {
    const arrayBuffer = await imageStream.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    document.getElementById(imageElementId).src = url;
    URL.revokeObjectURL(url);
  }
</script>

img要素に対して画像を表示するように設定しています。

次にIndex.razorは以下のようにします。

@page "/"
@inject IJSRuntime JS

<PageTitle>Index</PageTitle>

<InputFile OnChange="ResizeAndDisplayImageUsingStreaming" />

<img id="showImageHere" />

@code {
    //ファイルを選択するたびに実行される
    private async Task ResizeAndDisplayImageUsingStreaming(InputFileChangeEventArgs e)
    {
        //選択したファイルの取得
        var imageFile = e.File;

        //画像のサイズを変更
        var resizedImage = await imageFile.RequestImageFileAsync("image/jpg", 250, 250);
        
        //画像のストリームを取得
        var jsImageStream = resizedImage.OpenReadStream();
        
        var dotnetImageStream = new DotNetStreamReference(jsImageStream);
        
        //JavaScriptの関数を呼び出し
        await JS.InvokeVoidAsync("setImage", "showImageHere", dotnetImageStream);
    }
}

これで準備完了です。
あとはアプリを立ち上げ、ファイルの選択ボタンを押して表示したい画像ファイルを選ぶと画像が表示され・・・ません。

このようにうまく読み込めていない状態になります。

エラーメッセージは?

ブラウザの開発者ツールを利用すると、以下のようなエラーが出ています。

Failed to load resource: net::ERR_FILE_NOT_FOUND

どうやら元となるファイルが見つからないようです。

解決方法

以下のページに解決方法がありました。

github.com

JavaSctiptの

URL.revokeObjectURL(url);

となっているところを

setTimeout(() => URL.revokeObjectURL(url), 0);

と変更すると画像が表示されます。

setTimeoutは1つ目の引数で指定した処理を、2つ目の引数で指定した時間(ミリ秒)遅らせて実行するメソッドです。
詳しくは以下のページをご覧ください。 developer.mozilla.org

これを使うとURLを破棄するタイミングが遅くなるということなんでしょうか?
一旦はこの方法で回避しようと思います。

投稿者プロフィール
古川 貴浩

古川 貴浩

HoloLens 2アプリケーションの開発をしています。

執筆記事一覧