.NET TIPS

[ASP.NET MVC]ファイルのアップロードを行うには?[3.5、C#、VB]

山田 祥寛
2009/10/22

 ASP.NET MVCでは、クライアント(ブラウザ)からアップロードしたファイルをアクション・メソッドのHttpPostedFileBase型(System.Web名前空間)のパラメータにバインドするためのHttpPostedFileBaseModelBinderクラス(System.Web.Mvc名前空間)が用意されている。HttpPostedFileBaseModelBinderクラスを利用することで、ファイルのアップロード処理もごく直感的なコードで記述することができる。

 次の画面は、本稿で作成するファイル・アップロード処理のサンプル・アプリケーションの実行例だ。

ファイルを指定して[送信]ボタンをクリック
本稿で作成するサンプル・アプリケーション
クライアント側のファイルをサーバの決められたフォルダにアップロード。なお、アップロードできるファイルは画像ファイルに限定するものとする。

 誤解のしようもないサンプルであるので、さっそく具体的なコードを見ていくことにしよう。

 なお、本サンプル・プログラムを動作させるに当たっては、「連載:ASP.NET MVC入門 第1回 ASP.NET MVCフレームワーク 基本のキ」で紹介した手順に従って、ASP.NET MVCをインストールし、また、「ASP.NET MVC Web Application」プロジェクトを作成しておく必要がある。

1. アップロード・フォームを作成する

 まずは、アップロード・ファイルを指定するフォームから。以下は、Upload/Indexアクションと、それに対応するビュー・スクリプトである。アクション・メソッド(コントローラ・クラス)とビュー・スクリプトを作成する基本的な手順については、前述の記事をご参照いただきたい。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcAppCs.Controllers {
  public class UploadController : Controller {
    // アップロード・フォームを生成するUpload/Indexアクション
    public ActionResult Index() {
      return View();
    }
  }
}
Public Class UploadController
    Inherits System.Web.Mvc.Controller

  ' アップロード・フォームを生成するUpload/Indexアクション
  Function Index() As ActionResult
    Return View()
  End Function

End Class
アップロード・フォームを生成するUpload/Indexアクション(上がUploadController.cs/下がUploadController.vb)

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ファイルアップロード</title>
</head>
<body>
  <div>
    <% using (Html.BeginForm("Index", "Upload", FormMethod.Post, new {enctype = "multipart/form-data"})) { %>
      アップロードするファイル:
      <input type="file" name="fl" size="50" />
      <input type="submit" value="送信" />
    <% } %>
    <%--アップロード結果を表示させるためのプレイスホルダ--%>
    <div style="color:Red"><%=Html.Encode(ViewData["msg"])%></div>
  </div>
</body>
</html>
<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>ファイルアップロード</title>
</head>
<body>
  <div>
    <% Using (Html.BeginForm("Index", "Upload", FormMethod.Post, New With {.enctype = "multipart/form-data"}))%>
      アップロードするファイル:
      <input type="file" name="fl" size="50" />
      <input type="submit" value="送信" />
    <% End Using%>
    <%--アップロード結果を表示させるためのプレイスホルダ--%>
    <div style="color:Red"><%=Html.Encode(ViewData("msg"))%></div>
  </div>
</body>
</html>
アップロード・フォームを表すビュー・スクリプト(Upload/Index.aspx。上がC#、下がVisual Basic)

 Upload/Indexアクションについてはビュー・スクリプトを呼び出しているだけの最小限の構成なので、特筆すべき点はないだろう。

 ここで注目していただきたいのは、上記のビュー・スクリプトの太字で表した部分だ。Html.BeginFormメソッドは<form>タグを生成するためのビュー・ヘルパーである。

[構文]BeginFormメソッド
BeginForm([String action, String ctrl [,FormMethod method [,Object attrs]]])
 action:アクション名
 ctrl:コントローラ名
 method:method属性(GET/POST)
 attrs:そのほかの属性

 ファイルをアップロードするためには、<form>タグに「enctype="multipart/form-data"」属性を追加しなければならない。構文を見ても分かるように、BeginFormメソッドでaction、method以外の属性を指定したい場合には、attrsパラメータに匿名型の形式(属性名 = 値)で指定する必要がある。

2. アップロード処理を行うアクション・メソッドを定義する

 次に、アップロード処理を行うUpload/Index(fl)アクションを定義しておこう。

using System.IO;
  ……中略……

// アップロード処理を行うUpload/Indexアクション
// (HTTP POSTによる実行)
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(HttpPostedFileBase fl) {

  // コンテンツ・タイプが「image/*」であるか(画像ファイルか)
  // をチェック
  if (fl.ContentType.StartsWith("image/")) {

    // アップロード先のパスを生成
    var upfile = Server.MapPath("~/App_Data/Uploaded/") +
      Path.GetFileName(fl.FileName);

    // 同名のファイルが存在する場合はエラー
    if (System.IO.File.Exists(upfile)) {
      ViewData["msg"] = "同名のファイルが存在します。";
    } else {
      // 画像ファイルで同名のファイルが存在しない場合は保存処理
      fl.SaveAs(upfile);
      ViewData["msg"] = String.Format(
        "{0}をアップロードしました。", fl.FileName);
    }
  } else {
    // 画像ファイルでない場合はエラー
    ViewData["msg"] = "画像以外はアップロードできません。";
  }
  // 入力元のフォームに結果を表示
  return View();
}
Imports System.IO
  ……中略……

' アップロード処理を行うUpload/Indexアクション
'(HTTP POSTによる実行)
<AcceptVerbs(HttpVerbs.Post)> _
Function Index(ByVal fl As HttpPostedFileBase) As ActionResult

  ' コンテンツ・タイプが"image/*"であるか(画像ファイルか)
  ' をチェック
  If fl.ContentType.StartsWith("image/") Then

    ' アップロード先のパスを生成
    Dim upfile As String = Server.MapPath("~/App_Data/Uploaded/") _
      & Path.GetFileName(fl.FileName)

    ' 同名のファイルが存在する場合はエラー
    If System.IO.File.Exists(upfile) Then
      ViewData("msg") = "同名のファイルが存在します。"
    Else
      ' 画像ファイルで同名のファイルが存在しない場合は保存処理
      fl.SaveAs(upfile)
      ViewData("msg") = String.Format(
        "{0}をアップロードしました。", fl.FileName)
    End If
  Else
    ' 画像ファイルでない場合はエラー
    ViewData("msg") = "画像以外はアップロードできません。"
  End If
  ' 入力元のフォームに結果を表示
  Return View()
End Function
アップロードされたファイルを処理するためのUpload/Indexアクション(上がUploadController.cs/下がUploadController.vb)

 コードはやや長めだが、コンテンツ・タイプのチェック(画像ファイルであるか)、同名ファイルの存在チェックを行っているだけなので、これらについてはリスト内のコメントを参照いただきたい。AcceptVerbs属性は、HTTPメソッドによって処理を分岐するためのセレクタ属性である。詳細は、前述の記事をご覧いただくとよいだろう。

 ここでポイントとなるのは、リストの太字部分である。<input type="file" name="fl" ……>タグから送信されたアップロード・ファイルは、アクション・メソッドの同名の仮引数(この例では「fl」)にバインドされる。ここで注意すべき点は、仮引数の型はHttpPostedFileBaseクラスにしなければならないということだけだ。

 これによって、HttpPostedFileBaseModelBinderクラスが自動的にアップロード・ファイルをHttpPostedFileBaseクラスにバインドしてくれる。デフォルトのモデル・バインダであるDefaultModelBinderクラスと同じく、HttpPostedFileBaseModelBinderクラスは初期状態でアプリケーションに登録済みであるので、利用にあたって特にこれといった準備を行う必要はない。アプリケーション開発者は、通常、HttpPostedFileBaseModelBinderクラスの存在すら意識することはないはずだ。

 HttpPostedFileBaseオブジェクトにファイルがバインドされてしまえば、あとはSaveAsメソッドを使って、この内容を「~/App_Data/Uploaded/<元のファイル名>」に保存するだけだ*。SaveAsメソッドについては、「TIPS:[ASP.NET]ブラウザからファイルをアップロードできるようにするには?」で解説しているので、併せて参照していただきたい。

* アップロード先のApp_Data/Uploadedフォルダはあらかじめ作成しておく必要がある。

 以上を理解したら、「http://localhost:4419/Upload/Index」から、サンプルを実行してみよう(ポート番号は環境によって異なる可能性がある)。冒頭の画面のようにフォームから指定したファイルをアップロードできること、同名のファイルや画像以外のファイルをアップロードした場合にエラー・メッセージが表示されることを確認してほしい。End of Article

利用可能バージョン:.NET Framework 3.5
カテゴリ:Webフォーム 処理対象:ASP.NET MVC
使用ライブラリ:HttpPostedFileBaseModelBinderクラス(System.Web.Mvc名前空間)
使用ライブラリ:HttpPostedFileBaseクラス(System.Web名前空間)

この記事と関連性の高い別の.NET TIPS
[ASP.NET]ブラウザからファイルをアップロードできるようにするには?
[ASP.NET MVC]ASP.NET MVCでアップロードしたファイルをデータベースに登録するには?
[ASP.NET]アプリケーションからASP.NETサイトにファイルをアップロードするには?
[ASP.NET AJAX]AsyncFileUploadコントロールでファイルを非同期にアップロードするには?
[ASP.NET]アップロードされたファイルをPostedFileプロパティにより取得するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間