ASP.NET MVC - ファイルアップロード
ASP.NET MVC - ファイルアップロード
ASP.NET MVC でファイルをアップロードする方法を解説します。
以下の環境で確認しています。
- .NET Framework 4.6.2
- AspNet.Mvc 5.2.9
サンプルソース
以下のように HTML とアクションメソッドを準備します。
HTML
シンプルに昔ながらの <input type="file">
を form タグで送信する方法でいきます。
JavaScript は使いません。
<form action="/File/Upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile" />
<input type="submit" value="アップロード" />
</form>
<div>@Html.Encode(ViewBag.result)</div>
form タグの enctype 属性には multipart/form-data を設定してください。
アクションメソッド
コントローラー FileController を作り、次のように Upload メソッドを追加します。
Upload メソッドは、アップロードされたファイルを Web アプリルートの App_Data/Uploaded/[Guid]/元のファイル名 で保存します。
public class FileController : Controller
{
:
:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase uploadFile)
{
// 何も選択せずアップロードされた場合は入力エラー
if (uploadFile == null)
{
ViewBag.result = "ファイルを選択してください";
return View(nameof(FileController.Index));
}
try
{
// アップロードされたファイルの保存先を決める
var path = Path.Combine(Server.MapPath("~/App_Data/Uploaded"),
Guid.NewGuid().ToString(),
Path.GetFileName(uploadFile.FileName));
// ディレクトリがなければ作る
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
}
// アップロードされたファイルを保存する
uploadFile.SaveAs(path);
ViewBag.result = $"アップロード成功({Path.GetFileName(path)})";
}
catch (Exception ex)
{
ViewBag.result = $"アップロード失敗({ex.Message})";
}
return View(nameof(FileController.Index));
}
仮引数の型を HttpPostedFileBase クラスにします。
また仮引数の名前は HTML の input タグの name 属性と一緒にしてください。
(今回は name=“uploadFile” なので、uploadFile とします)
このようにするだけで、あとはモデルバインダがアップロードされたファイルの情報を引数として使えるようにしてくれます。
もし何のファイルも選択せずにアップロードされた場合、引数は null となります。
アップロードされたファイルを保存するには、SaveAs メソッドを使います。
複数ファイルのアップロード
HTML
<input type="file">
に multiple 属性を付けます。
<form action="/File/Upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFiles" multiple />
<input type="submit" value="アップロード" />
</form>
アクションメソッド
仮引数の型をリストにします。HttpPostedFileBase
→ IEnumerable<HttpPostedFileBase>
リストの件数分、アップロードされたファイルに対する処理を繰り返します。
foreach (var file in uploadFiles)
{
// TODO: アップロードファイルに対する処理を書く
}
以下のコードは、アップロードされたファイルすべてを Web アプリルートの App_Data/Uploaded/[Guid] フォルダに元のファイル名で保存します。
[HttpPost]
public ActionResult Upload(IEnumerable<HttpPostedFileBase> uploadFiles)
{
// 何も選択せずアップロードされた場合は入力エラー
if (uploadFiles == null || !uploadFiles.Any())
{
ViewBag.result = "ファイルを選択してください";
return View(nameof(FileController.Index));
}
// アップロードされたファイルの保存先フォルダを決める
var folderPath = Path.Combine(Server.MapPath("~/App_Data/Uploaded"),
Guid.NewGuid().ToString());
// フォルダがなければ作る
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
// アップロードされたファイルすべてを、所定のフォルダに元のファイル名で保存する
foreach (var file in uploadFiles)
{
file.SaveAs(Path.Combine(folderPath, Path.GetFileName(file.FileName)));
}
return View(nameof(FileController.Index));
}
ファイルサイズを制限する
HttpPostedFileBase クラスの ContentLength プロパティを使います。
アップロードされたファイルのサイズ(バイト単位)が取得できます。
例)空のファイルを禁止する場合
if (uploadFile.ContentLength == 0)
{
// TODO: 空ファイル(0バイト)はエラーにする
}
ファイルの種類を制限する
HttpPostedFileBase クラスの ContentType プロパティを使います。
アップロードされたファイルの MIME コンテンツタイプが取得できます。
例)プレーンテキストだけを許可する場合
if (uploadFile.ContentType != "text/plain") {
// TODO: プレーンテキスト以外はエラーにする
}
例)画像ファイルだけを許可する場合
if (!uploadFile.ContentType.StartsWith("image/"))
{
// TODO: 画像以外はエラーにする
}
413 Request Entity Too Large の対処方法
このエラーは、リクエストのサイズが、Web サーバーによって処理されるリクエストの最大サイズを超えている場合に発生します。
リクエストの最大サイズの見直しで対処します。
web.config ファイルの /configuration/system.webServer/security/requestFiltering/requestLimits@maxAllowedContentLength に設定します。
詳細は「ASP.NET - 413 Request Entity Too Large の対処方法」のとおりです。
HttpException: 要求の長さの最大値を超えました。 の対処方法
この例外も Request Entity Too Large の場合と同様で、リクエストのサイズが大きい場合に発生します。
設定ファイルの見直しで対処しますが、設定箇所が異なります。
web.config の /configuration/system.web/httpRuntime@maxRequestLength に設定します。
詳細は「ASP.NET - HttpException: 要求の長さの最大値を超えました。 の対処方法」のとおりです。
maxAllowedContentLength と maxRequestLength を設定した結果、約2GB(約21億4748万バイト ……2GBよりは若干少ない)までのファイルはアップロードできるようになりました。
ちなみに2GB以上は次のエラーになりました。
直訳「ASP.NET が URL 内で無効な文字を検出しました」ですが、はたして原因は……。
HTTP Error 400.0 - Bad Request
ASP.NET detected invalid characters in the URL.
アカウントを作成 して、もっと沢山の記事を読みませんか?
この記事にコメントをしてみませんか?