初めまして、アキちゃんです。
備忘録をかねてブログを書くことにしました。
今回はBlazor Serverで簡易ファイル共有(前編:ファイルアップロード)について書きます。
それでは早速・・・Blazor Serverで簡易ファイル共有(前編:ファイルアップロード)!
Lesson.1 事の発端
たまにファイルを共有したいことがありますよね、なのでアップロードしたファイルを共有できる簡易ファイル共有アプリを作ろうと思います。
Lesson.2 プロジェクト作成(FileShare)
プロジェクト名はFileShareで、Blazor Server プロジェクト(.Net6)で作成します。
基本デフォルトのまま次へ押しとけば大丈夫ですが一応以下記事にまとめています。
Lesson.3 事前準備
今回は取り敢えずファイルアップロードを実装しようと思います。
作成したプロジェクトのwwwrootの下にshareフォルダを作成します。
プロジェクト直下にControllersというフォルダを作成します。
ファイルのアップロードとダウンロードはControllerから取得したいのでProgram.csに以下のコードを追加します。
app.UseRouting();
app.UseEndpoints(userEndPpoints =>
{
userEndPpoints.MapControllers();
});
app.MapBlazorHub();
Controllerを使用するためHttpRequestMessageを使用したいため、Program.csに以下コードを追記します。
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddHttpClient();
var app = builder.Build();
ここまででプロジェクトファイルは以下のようになっていると思います。
Lesson.4 ファイルアップロード
ファイルをアップロードするコントローラーを作りたいため、Controllerフォルダに 追加→コントローラー→MVCコントローラー - 空 を選択し、UploadController.csを作成します。
できたUploadController.csをざっくり以下のように修正します。
UploadController.cs(クリックで展開) UploadController.cs(クリックで圧縮)
using Microsoft.AspNetCore.Mvc;
namespace FileShare.Controllers
{
public class UploadController : Controller
{
private readonly IWebHostEnvironment environment;
public UploadController(IWebHostEnvironment environment)
{
this.environment = environment;
}
[Route("api/upload/file")]
public async Task<IActionResult> UploadDocument(IFormFile file)
{
try
{
using (var memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
var data2 = memoryStream.ToArray();
var filePath = Path.Combine(environment.WebRootPath + @"\share", file.FileName);
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
fs.Write(data2, 0, data2.Length);
fs.Close();
}
};
return StatusCode(200);
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
}
}
ファイルをアップロードする画面を作りたいため、Pagesフォルダに追加→Razorコンポーネントを選択し、Upload.razorを作成します。
できたUpload.razorをざっくり以下のように修正します。
Upload.razor(クリックで展開) Upload.razor(クリックで圧縮)
@page "/upload"
@inject IHttpClientFactory ClientFactory
<label style=" height:30px;line-height:30px;color:black;background-color:greenyellow; border-radius: 5px; ">
ファイル選択
<InputFile style="display:none" OnChange="@(args => FileUpload(args))" />
</label>
@code {
async Task FileUpload(InputFileChangeEventArgs e)
{
foreach (var file in e.GetMultipleFiles())
{
var ms = new MemoryStream();
await file.OpenReadStream(file.Size).CopyToAsync(ms);
ms.Position = 0;
var fileContent = new StreamContent(ms);
using var content = new MultipartFormDataContent();
content.Add(fileContent, "file", file.Name);
var request = new HttpRequestMessage(HttpMethod.Post, "https://localhost:7281" + "/api/upload/file");
var client = ClientFactory.CreateClient();
{
request.Content = content;
await client.SendAsync(request);
}
}
}
}
upload.razorにアクセスできるようにするために、Shared/NavMenu.razorを以下のように修正します。
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="upload">
<span class="oi oi-data-transfer-upload" aria-hidden="true"></span> Upload
</NavLink>
</div>
</nav>
</div>
ここまできたら実行しUploadを選択後、ファイル選択を押下します。
表示された開く画面から任意のファイルを選択し開くorダブルクリックします。
表示された開く画面が閉じた後、プロジェクトのwwwroot/shareフォルダに選択したファイルがアップロードされているはずです。
Lesson.5 あとがき
年明けましたね!
年末年始忙しすぎて全然記事書けなかった!
ソースコードは後編で公開します。
また、記事では使用しないように実装しましたが
OpenReadStream().ReadAsync(buffer)
を使用するとうまく動作しないみたいです。詳しくは以下記事を確認ください。