Web アプリを作るときに、画像をアップロードする機能が必要になることも多いと思います。
ファイルは外部のファイルストレージサービスにアップロードするのが一般的で、今回は Azure Blob Storage を使用した手順を解説します。
Azure Blob Storage に画像をアップロードする手順
ストレージアカウントの作成
Azure ポータルにアクセスして、ストレージアカウントのメニューから作成をします。
サブスクリプションやリソースグループ、ストレージアカウント名を指定します。
地域は一番近い Japan East を指定し、パフォーマンスと冗長性はテスト用なので一番低いものを選んでおけばいいでしょう。
アクセス層もアクセス頻度の低い「クール」を選択しました。
後の設定は初期値で問題ありませんので、そのまま作成します。
このあと、ストレージアカウントの接続文字列が必要になるので、アクセスキーのメニューからコピーしておきましょう。
Blazor プロジェクトの作成
今回は、ASP.NET Core でホストされた Blazor WebAssembly プロジェクトを作成しました。
NuGet パッケージの追加
Server プロジェクトに対して、Azure.Storage.Blobs の NuGet パッケージを追加します。
このパッケージ追加により、Azure Blob Storage にアップロードするための API が使えるようになります。
接続文字列の設定
Server プロジェクトの appsettings.json に、ConnectionStrings のセクションを作成します。
AzureConnectionString のキーで先ほどコピーした接続文字列を設定してください。
API を実行するときに必要になります。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"ConnectionStrings": {
"AzureConnectionString": "コピーした接続文字列"
},
"AllowedHosts": "*"
}
Controller クラスの作成
Azure にアップロードするための Controller クラスを Server プロジェクトに作成します。
using System.Net.Mime;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Microsoft.AspNetCore.Mvc;
namespace BlazorFileUploadTest.Server.Controllers;
[Route("api/[controller]")]
public class UploadAzureController : ControllerBase
{
private readonly string azureConnectionString;
public UploadAzureController(IConfiguration configuration)
{
azureConnectionString = configuration.GetConnectionString("AzureConnectionString");
}
[HttpPost("[action]")]
[Produces(MediaTypeNames.Application.Json)]
public async Task<ActionResult<IEnumerable<string>>> Upload([FromForm(Name = "images")] IFormFileCollection files)
{
List<string> uploadUrls = new();
foreach (var file in files)
{
var container = new BlobContainerClient(azureConnectionString, "upload-container");
// コンテナが作成されていなければ作成
var createResponse = await container.CreateIfNotExistsAsync();
// BLOB へのアクセス許可
if (createResponse != null && createResponse.GetRawResponse().Status == 201)
await container.SetAccessPolicyAsync(PublicAccessType.Blob);
// フォルダ階層の指定
var blob = container.GetBlobClient($"images/{Guid.NewGuid()}/{DateTime.Now:yyyyMMddHHmmssfff}");
// すでにファイルがあれば削除
await blob.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots);
// BLOB にアップロード
using (var fileStream = file.OpenReadStream())
{
await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = file.ContentType });
}
uploadUrls.Add(blob.Uri.ToString());
}
// アップロードしたファイルの URL を返却
return Ok(uploadUrls);
}
}
ファイルをアップロードするためには、コンテナーを作る必要があります。
コンテナー名は小文字とする必要があり、今回は upload-container という名前にしました。
コンテナーの中には階層を作ることができるので、Guid の下にタイムスタンプのファイル名でアップロードすることにしました。
実際には、ユーザー ID を階層にするとわかりやすいでしょう。
ファイルをアップロードした後は、ファイルの URL を返却しています。
画面の作成
ファイルをアップロードする画面を作成していきます。
@page "/file-upload"
@inject HttpClient HttpClient
@using System.Net.Http.Headers
<InputFile OnChange="@HandleSelected" multiple />
@if (ImgUrls is not null)
{
@foreach (var url in ImgUrls)
{
<div>
<img src="@url" class="image-preview" style="width: 300px" />
</div>
}
}
@code{
public IEnumerable<string>? ImgUrls { get; set; }
private async Task HandleSelected(InputFileChangeEventArgs e)
{
long maxFileSize = 1024 * 1024 * 15;
using (var content = new MultipartFormDataContent())
{
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
foreach (var imageFile in e.GetMultipleFiles())
{
var fileContent = new StreamContent(imageFile.OpenReadStream(maxFileSize));
content.Add(fileContent, "images", imageFile.Name);
}
var response = await HttpClient.PostAsync("api/UploadAzure/Upload", content);
ImgUrls = await response.Content.ReadFromJsonAsync<IEnumerable<string>?>();
}
}
}
ファイルの選択コンポーネントのみのシンプルな画面で、アップロードが完了したら画像を画面に表示します。
ファイルの最大サイズは 15 MB です。
InputFile コンポーネントに multiple を指定することで、複数ファイルを一度にアップロードできるので、GetMultipleFiles ですべてのファイルを取得して Form データに追加しています。
Form に詰め込んだデータは、Controller で FromForm の属性をつけることで引数で受け取ることができます。
動作確認
動作確認をしていきましょう。
File Upload のメニューを用意しましたが、直接 URL を指定しても問題ありません。
ファイルは複数指定できるようにしているので、今回は2つ指定してアップロードしました。
正常にアップロードできた場合は、アップロード先の URL が返却され、画面に画像が表示されます。
Azure のコンテナーを見てみましょう。
プログラムで指定した「upload-container」という名前で作成され、ファイルの数だけフォルダができていることが確認できます。
フォルダの中を見ると、ファイル名がタイムスタンプになっている画像が入っていますね。
最後に
Azure Blob Storageに画像をアップロードする手順を解説しました。
ファイルのアップロードは少し複雑なので、専用のコンポーネントを採用したほうが実装が楽になるかもしれません。
本記事を参考に、作成中のアプリにファイルのアップロード機能を組み込んでみてください。
入門編から EC サイトを作る応用編まで、Blazor の本を3冊執筆しました。
私が1年以上かけて学習した内容をすべて詰め込んでいるので、さらにステップアップしたい方はぜひご覧ください。