ASP.NET Core アプリケーションの Razor Pages でファイルをアップロードするコードを紹介します。
概要
Razor Pages でファイルをアップロードする場合はinputタグのファイル選択コントロールを利用します。ページモデルで参照できるようにするため、
タグヘルパーを利用し、
asp-for
属性を指定してページモデルにバインドします。
プログラム
ASP.NET Core Webアプリケーションを作成します。 ターゲットフレームワークは.NET 5を利用しています。
コード
以下のコードを記述します。
startup.csにはRazor Pagesの基本的な設定を記述します。ConfigureServices メソッドにAddRazorPages()メソッドの記述、
UseEndpoints メソッド内にページマップのMapRazorPages()メソッドを記述します。
詳しくは
こちらの記事を参照してください。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FileUpload
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
}
Pagesフォルダを作成し、Razorページのファイルを配置します。
simple-upload.cshtml がファイルをアップロードするページになります。
input タグを配置し、
type="file"
を指定し、ファイル選択コントロールとします。また、
asp-for
属性に
ページモデルクラスの "FileData" プロパティを指定します。
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model FileUpload.Pages.simple_uploadModel
@{
}
<html>
<head>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
<input type="submit" value="POST" />
</form>
</body>
</html>
simple-upload.html.cs は simple-upload.cshtml のページモデルクラスです。
FileData
プロパティを宣言します。プロパティには
BindProperty
属性を付与します。
BindProperty属性については
こちらの記事もを参照してください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Http;
namespace FileUpload.Pages
{
public class simple_uploadModel : PageModel
{
[BindProperty]
public IFormFile FileData { get; set; }
public void OnGet()
{
}
public IActionResult OnPost()
{
System.IO.Stream stream = FileData.OpenReadStream();
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
System.IO.FileStream fs = new System.IO.FileStream(FileData.FileName, System.IO.FileMode.CreateNew);
fs.Write(buffer, 0, buffer.Length);
fs.Close();
stream.Close();
return RedirectToPage("/simple-upload-complete");
}
}
}
simple-upload-complete.cshtml はアップロード完了時に表示されるページです。
ページ内にアップロード完了のメッセージを表示します。
@page
@model FileUpload.Pages.aaaModel
@{
}
<html>
<head>
</head>
<body>
<p>ファイルをアップロードしました。</p>
</body>
</html>
simple-upload-complete.html.cs は simple-upload-complete.htmlのページモデルです。標準で生成されたコードから変更はありません。
simple-upload-complete.cshtmlの@model参照を削除し、simple-upload-complete.html.csを削除してページモデルを使用しない状態にしても問題ありません。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace FileUpload.Pages
{
public class aaaModel : PageModel
{
public void OnGet()
{
}
}
}
ファイルの配置
ファイルの配置は下図の通りです。
解説
simple-upload.cshtml
formタグ内にinputコントロールを配置します。formタグの
method
属性は post に設定し、ポストでフォームを送信します。
また、バイナリファイルを送信するため、
enctype
属性に "multipart/form-data" を指定します。
inputタグは
type
属性に "file" を指定しファイル選択コントロールとします。
asp-for
属性にはページモデルクラスのFileDataプロパティを設定します。
<form method="post" enctype="multipart/form-data">
<div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
<input type="submit" value="POST" />
</form>
simple-upload.cshtml.cs
simple-upload.cshtml のページモデルクラスでは、クラスにFileData プロパティを宣言します。
ページから参照できるようにするため、[BindProperty]属性を付与します。
[BindProperty]
public IFormFile FileData { get; set; }
フォームからポスト処理された際にページモデルクラスで実行されるコードが以下のOnPostメソッドになります。
アップロードされたファイルを読み取るため、FileDataプロパティのOpenReadStream() メソッドを呼び出します。アップロードされたファイルを読み取るストリームが取得できます。
ストリームのReadメソッドを呼び出し、ファイルのバイナリ情報をbyte配列に読み取ります。
アップロードされたファイルをサーバーのディスク上に配置します。今回はコードをシンプルにするため、アプリケーションのカレントディレクトリに
配置するコードとしています。ファイルを書き込むため、FileStereamクラスを作成します。コンストラクタの第一引数にファイル名を与えます。
アップロードされたファイル名が
FileData.FileName
プロパティに代入されているため、同じ名前で保存します。台に引数にはファイルを新規作成する
FileMode.CreateNew
フラグを与えます。
ファイルストリームのWriteメソッドを呼び出し、byte配列の情報をファイルに書き込みます。
処理の完了後にリダイレクト処理を実行し、アップロード完了メッセージのあるぺージを表示します。
public IActionResult OnPost()
{
System.IO.Stream stream = FileData.OpenReadStream();
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
System.IO.FileStream fs = new System.IO.FileStream(FileData.FileName, System.IO.FileMode.CreateNew);
fs.Write(buffer, 0, buffer.Length);
fs.Close();
stream.Close();
return RedirectToPage("/simple-upload-complete");
}
実行結果
プロジェクトを実行します。Webブラウザが起動しますので、
(Webアプリケーションのルート)/simple-upload
のURLにアクセスします。
下図のページが表示されます。ページの[ファイルの選択]ボタンをクリックします。
ファイル選択ダイアログボックスが表示されます。アップロードしたいファイルをクリックして選択し、[開く]ボタンをクリックします。
ファイルが選択された状態になります。[ファイルの選択]ボタンの右側に選択されたファイル名が表示されます。
ファイル選択後[POST]ボタンをクリックします。
ファイルのアップロードが実行され、
simple-upload-complete
ページにリダイレクトされます。ファイルがアップロードされた旨のメッセージが表示されます。
ファイルがアップロードされているか確認します。ASP.NET Webアプリケーションのフォルダをエクスプローラで開きます。先ほどアップロードした、
image.png ファイルが配置されていることが確認できます。
image.pngファイルを開きます。ファイルの内容も問題ないです。
補足
ファイルを保存するためのFileStreamの作成時に
FileMode.CreateNew
を指定しているため、同じファイル名のファイルを再アップロードすると、
既にファイルが存在している旨の例外が発生します。回避するには、
FileMode.Create
を指定して上書きを許可するモードでFileStreamを作成するか、ファイルの重複判定をして
同じファイルで保存されない仕組みを実装する必要があります。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2021-05-02
作成日: 2020-12-28