Lightning Blog
Blazor記事イメージ画像

【Blazor】 InputFileを使ったBlazorファイルアップロード&ダウンロード

更新日:2024/06/20
この記事では、.NET5から追加されたInputFileを使って、ファイル読み込み後にアップロードする方法を解説します。 また合わせて、ファイルをダウンロードする方法も解説します。

    目次

  • ファイルのアップロード
  • ファイルのダウンロード
  • まとめ

ファイルのアップロード

セクション画像

.NET5以降では、InputFileコンポーネントを使って、ファイルを読み込むことができます。 今回は、外部からファイルを読み込み後、wwwroot/uploadへファイルをアップロードするサンプルになります。

以下サンプルコードになります。


@page "/upload"
@using Microsoft.AspNetCore.Components.Forms
@inject IWebHostEnvironment WebHostEnvironment

<h3>アップロード検証</h3>
<hr />
<p><var>wwwroot/upload</var>をアップロード</p>
<InputFile OnChange="ChangeFileAsync" />

@if (!string.IsNullOrEmpty(Message))
{
    <p>@Message</p>
}

@code {
    /// <summary>
    /// メッセージ
    /// </summary>
    private string Message = string.Empty;

    /// <summary>
    /// ファイルサイズの上限値(今回は 10MB に設定)
    /// </summary>
    private long maxFileSize = 10485760;

    /// <summary>
    /// ファイル変更時の処理
    /// </summary>
    /// <param name="e">イベント引数</param>
    private async Task ChangeFileAsync(InputFileChangeEventArgs e)
    {
        IBrowserFile file = e.File;
        if (file.Size > maxFileSize)
        {
            Message = $"ファイルサイズが大きすぎます。最大 {maxFileSize / (1024 * 1024)} MB までアップロード可能です。";
            return;
        }

        var uploadPath = Path.Combine(WebHostEnvironment.WebRootPath, "upload");
        Directory.CreateDirectory(uploadPath);

        var filePath = Path.Combine(uploadPath, file.Name);

        // ファイルサイズ制限(maxFileSize)を設定
        using var fileStream = file.OpenReadStream(maxFileSize); 
        using var memoryStream = new MemoryStream();
        await fileStream.CopyToAsync(memoryStream);
        await File.WriteAllBytesAsync(filePath, memoryStream.ToArray());

        Message = $"{file.Name}がアップロードされました。";
    }
}

InputFileコンポーネントでは、OnChangeにファイル選択時の処理を登録することができます。 登録できるのは、InputFileChangeEventArgsを引数にもつメソッドChangeFileAsyncになります。

ChangeFileAsyncメソッドでは、イベント引数からIBrowserFileを取得しています。 IBrowserFileインターフェースを通じて、ファイル名やファイルサイズ等の情報を取得したり、 ファイルを読み取るためのストリームを開くOpenReadStreamを呼び出すことができます。

OpenReadStreamでは、引数にファイルサイズの最大許容サイズ(バイト単位)を指定することができます。 指定しない場合は、512KBまでに制限されます。 今回は、10MBを許容値とするため、それをバイトへ変換した10485760を指定しています。 アップロードするデータに応じて、調整してみてください。 ちなみに、許容値は超えた場合は、以下のようなエラーになります。


【以下のようなエラーになる】
Error: System.IO.IOException: Supplied file with size 660890 bytes exceeds the maximum of 512000 bytes.

最後に、OpenReadStreamで読み取ったファイルデータを、memoryStreamを使ってメモリ内に一時的にコピーし、 ファイルのアップロード先であるfilePathに書き込んでいます。

動作確認をしてみると、ファイル選択後にwwwroot/uploadにデータがアップロードされていることが確認できます。

動作確認
ファイル選択後の画面
動作確認
ファイルアップロード確認

ファイルのダウンロード

セクション画像

[wwwroot/download/Test.pdf]をダウンロードするサンプルを見ていきます。 ファイルのダウンロードは、JavaScriptを介して実行する必要があります。

まずダウンロードを行うJavaScriptのソースを見ていきます。


// ファイルダウンロード
function downloadFile(data) {
    // Blob作成
    const blob = new Blob([data.byteArray], { type: data.contentType });

    // ダウンロード可能なリンクを作成
    const url = URL.createObjectURL(blob);

    // URL からのダウンロードを開始する
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = data.fileName ?? '';
    anchorElement.click();
    anchorElement.remove();

    // URLの後始末
    URL.revokeObjectURL(url);
}

このdownloadFileメソッドでは、Blobを作成して、ダウンロード可能なURLを作成しています。 そのURLから<a>タグを作成して、クリック処理を行うことによってダウンロードを実現しています。

Blobについて知りたい方は、以下の記事を参考にしてみてください。

【Blobとは何か理解していない方へ】 https://zenn.dev/kazu1/articles/736991963449d6

次にjavascriptの参照を追加します。


@using Microsoft.AspNetCore.Components.Web
@namespace Blazor_UploadAndDownload.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link href="Blazor_UploadAndDownload.styles.css" rel="stylesheet" />
    <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
    @RenderBody()

    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>

    <script src="_framework/blazor.server.js"></script>

    @* ↓↓↓ ここに追記必要 ↓↓↓ *@
    <script src="js/functions.js"></script>
</body>
</html>

33行目のようにjavascript参照するコードを追加してください。

最後にダウンロードページを作成します。以下サンプルコードになります。


@page "/download"
@inject IJSRuntime JSRuntime
@inject IWebHostEnvironment WebHostEnvironment

<h3>ダウンロード検証</h3>
<hr />
<p>[wwwroot/download/Test.pdf]をダウンロード</p>
<button @onclick="DownloadFileAsync">ダウンロード</button>

@code {
    private async Task DownloadFileAsync()
    {
        // ファイルのバイナリデータを取得
        var filePath = Path.Combine(WebHostEnvironment.WebRootPath, "download", "Test.Pdf");
        var fileBytes = await File.ReadAllBytesAsync(filePath);
        var fileName = "Test.Pdf";
        var contentType = "application/pdf";

        // JavaScriptの関数(downloadFromByteArray)を呼び出して、ダウンロードを開始する
        await JSRuntime.InvokeVoidAsync(
            "downloadFile",
            new
            {
                byteArray = fileBytes,
                contentType = contentType,
                fileName = fileName
            });
    }
}

javascriptのメソッドdownloadFileメソッドをIJSRuntimeを介して呼び出しています。 引数には、ファイルのバイナリデータbyteArrayやMIMEタイプcontentType、ファイル名fileNameを渡しています。

動作確認してみると、 [wwwroot/download/Test.pdf]からPDFをダウンロードすることが確認できます。

動作確認

まとめ

セクション画像

今回は、ファイルのアップロードとダウンロードする方法について解説しました。 CSVファイルのアップロードやレポートのダウンロードはよく使う機能だと思いますので、是非活用してみてください。


ブログ内の記事で書かれているサンプルコードは、GitHubから確認する事ができます。 是非参考にしてみてください。

この本では、Blazorの基本から高度なテクニックまで、実際のプロジェクトに役立つ知識を網羅しています。 初心者から経験者まで、Blazorを扱うすべての開発者にとっての必読書です。 この記事の執筆者も参考にした「Blazor入門」で、あなたのBlazorスキルを飛躍的に向上させませんか?

合わせて読みたい

カード画像
コンポーネントにのみCSSを適用する方法

Blazorで特定のコンポーネントに限定したCSSを適用する方法を紹介。.NET5から導入されたCSS分離を活用し、他のコンポーネントやライブラリとのCSS競合を回避。コンポーネント[CssIsolationComponent.razor]とそのCSS[CssIsolationComponent.razor.css]を作成。この技術により、[CssIsolationComponent.razor]のpタグ部分の背景だけが赤くなることを示す。効率的なデザイン管理のためにCSS分離の使用を推奨。

更新日:2023/07/26

カード画像
Virtualizeコンポーネントの使い方

Blazorの仮想化コンポーネントを活用し、大量のデータを効率的に表示する方法を解説。画面内の要素のみをレンダリングし、スクロール時にデータを動的に読み込む手法や注意点を説明。

更新日:2023/07/26

An error has occurred. This application may no longer respond until reloaded. Reload 🗙