【Blazor】 InputFileを使ったBlazorファイルアップロード&ダウンロード
- ファイルのアップロード
- ファイルのダウンロード
- まとめ
目次
ファイルのアップロード

.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ファイルのアップロードやレポートのダウンロードはよく使う機能だと思いますので、是非活用してみてください。
この本では、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