ファイルのアップロード (C#)
ユーザーがバイナリ ファイル (Word や PDF ドキュメントなど) を Web サイトにアップロードし、サーバーのファイル システムまたはデータベースに保存できるようにする方法について学習します。
はじめに
これまでに調べたすべてのチュートリアルでは、テキスト データのみを操作してきました。 しかし、多くのアプリケーションには、テキスト データとバイナリ データの両方をキャプチャするデータ モデルがあります。 オンライン出会い系サイトでは、ユーザーが自分のプロファイルに関連付ける写真をアップロードできる場合があります。 求人 Web サイトでは、ユーザーが履歴書を Microsoft Word または PDF ドキュメントとしてアップロードできる場合があります。
バイナリ データを操作する場合、さらに新たな一連の課題が発生します。 バイナリ データをアプリケーションに保存する方法を決定する必要があります。 新しいレコードの挿入に使用されるインターフェイスは、ユーザーが自分のコンピューターからファイルをアップロードできるように更新する必要があります。また、レコードの関連付けられているバイナリ データをダウンロードするための手段を表示または提供するための追加の手順を行う必要があります。 このチュートリアルと次の 3 つのチュートリアルでは、これらの課題を乗り越える方法について調べます。 これらのチュートリアルの最後に、写真と PDF パンフレットを各カテゴリに関連付ける完全に機能するアプリケーションを構築することになります。 この特定のチュートリアルでは、バイナリ データを保存するためのさまざまな手法を確認し、ユーザーが自分のコンピューターからファイルをアップロードし、Web サーバーのファイル システムに保存できるようにする方法について調べます。
Note
アプリケーションのデータ モデルの一部であるバイナリ データは、Binary Large OBject の頭字語である BLOB と呼ばれることもあります。 これらのチュートリアルでは、BLOB という用語は同義ですが、バイナリ データという用語を使用することにしました。
手順 1: バイナリ データの操作 Web ページの作成
バイナリ データのサポートの追加に関する課題を調べ始める前に、まず、少し時間を取って、このチュートリアルと次の 3 つチュートリアルのために必要な ASP.NET ページを Web サイト プロジェクトに作成してみましょう。 まず、BinaryData
という名前の新しいフォルダーを追加します。 次に、次の ASP.NET ページをそのフォルダーに追加し、各ページを Site.master
マスター ページに関連付けます。
Default.aspx
FileUpload.aspx
DisplayOrDownloadData.aspx
UploadInDetailsView.aspx
UpdatingAndDeleting.aspx
図 1: バイナリ データ関連のチュートリアルの ASP.NET ページを追加する
他のフォルダーと同様に、BinaryData
フォルダーの Default.aspx
のセクションにチュートリアルが一覧表示されます。 SectionLevelTutorialListing.ascx
ユーザー コントロールではこの機能が提供されていることを思い出してください。 そのため、このユーザー コントロールをソリューション エクスプローラーからページのデザイン ビューにドラッグして Default.aspx
に追加します。
図 2: SectionLevelTutorialListing.ascx
ユーザー コントロールを Default.aspx
に追加する (クリックするとフルサイズの画像を表示されます)
最後に、これらのページをエントリとして Web.sitemap
ファイルに追加します。 具体的には、GridView の拡張 <siteMapNode>
の後に次のマークアップを追加します。
<siteMapNode
title="Working with Binary Data"
url="~/BinaryData/Default.aspx"
description="Extend the data model to include collecting binary data.">
<siteMapNode
title="Uploading Files"
url="~/BinaryData/FileUpload.aspx"
description="Examine the different ways to store binary data on the
web server and see how to accept uploaded files from users
with the FileUpload control." />
<siteMapNode
title="Display or Download Binary Data"
url="~/BinaryData/DisplayOrDownloadData.aspx"
description="Let users view or download the captured binary data." />
<siteMapNode
title="Adding New Binary Data"
url="~/BinaryData/UploadInDetailsView.aspx"
description="Learn how to augment the inserting interface to
include a FileUpload control." />
<siteMapNode
title="Updating and Deleting Existing Binary Data"
url="~/BinaryData/UpdatingAndDeleting.aspx"
description="Learn how to update and delete existing binary data." />
</siteMapNode>
Web.sitemap
を更新した後、少し時間を取って、ブラウザーを介してチュートリアル Web サイトを表示します。 左側のメニューに、バイナリ データの操作に関するチュートリアルの項目が含まれるようになりました。
図 3: サイト マップに、バイナリ データの操作に関するチュートリアルのエントリが含まれるようになった
手順 2: バイナリ データを保存する場所の決定
アプリケーションのデータ モデルに関連付けられているバイナリ データは、2 つの場所のいずれか (データベースに保存されているファイルへの参照を持つ Web サーバーのファイル システム上、またはデータベース自体内に直接) に保存できます (図 4 を参照)。 各方法には独自の一連の長所と短所があり、より詳細な議論を行う価値があります。
図 4: バイナリ データはファイル システムまたはデータベースに直接保存できる (クリックするとフルサイズの画像が表示されます)
Northwind データベースを拡張して、写真を各製品に関連付ける必要があるとします。 1 つのオプションは、Web サーバーのファイル システムにこれらの画像ファイルを保存し、Products
テーブルにパスを記録することです。 この方法では、おそらく、varchar(200)
型の Products
テーブルに ImagePath
列を追加します。 ユーザーがチャイの写真をアップロードすると、その写真は Web サーバーのファイル システム (~/Images/Tea.jpg
) に保存される可能性があります。ここで、~
はアプリケーションの物理パスを表します。 つまり、Web サイトが物理パス C:\Websites\Northwind\
でルート化されている場合、~/Images/Tea.jpg
は C:\Websites\Northwind\Images\Tea.jpg
と同等になります。 画像ファイルをアップロードした後、Products
テーブルのチャイ レコードを更新して、ImagePath
列で新しい画像のパスが参照されるようにします。 すべての製品画像をアプリケーションの Images
フォルダーに配置することにした場合、~/Images/Tea.jpg
または単に Tea.jpg
を使用することができます。
バイナリ データをファイル システムに保存する主な利点は次のとおりです。
- 実装が簡単: 後で簡単に説明しますが、データベース内に直接バイナリ データを保存したり、それを取得するには、ファイル システムを介してデータを操作する場合よりも少し多くのコードが必要になります。 さらに、ユーザーがバイナリ データを表示またはダウンロードするには、そのデータの URL を表示する必要があります。 データが Web サーバーのファイル システムに存在する場合、URL は簡単です。 ただし、データがデータベースに保存されている場合は、データベースからデータを取得して返す Web ページを作成する必要があります。
- バイナリ データへのより広範なアクセス: データベースからデータをプルできない他のサービスまたはアプリケーションからバイナリ データにアクセスできる必要がある場合があります。 たとえば、各製品に関連付けられている画像を FTP 経由でユーザーが使用できるようにする必要がある場合もあります。その場合は、バイナリ データをファイル システムに保存する必要があります。
- パフォーマンス: バイナリ データがファイル システムに保存されている場合、バイナリ データがデータベース内に直接保存されている場合よりも、データベース サーバーと Web サーバー間の需要とネットワークの輻輳が少なくなります。
ファイル システムにバイナリ データを保存する場合の主な欠点は、データをデータベースから切り離すことです。 レコードが Products
テーブルから削除された場合、Web サーバーのファイル システム上の関連付けられているファイルは自動的に削除されません。 ファイルを削除するために追加のコードを記述する必要があります。そうしないと、ファイル システムが未使用の孤立したファイルで乱雑になります。 さらに、データベースをバックアップする場合は、ファイル システム上の関連するバイナリ データのバックアップも必ず行う必要があります。 データベースを別のサイトまたはサーバーに移動すると、同様の課題が発生します。
バイナリ データは、varbinary
型の列を作成することで、Microsoft SQL Server 2005 データベースに直接保存することもできます。 他の可変長データ型と同様に、この列に保持できるバイナリ データの最大長を指定できます。 たとえば、最大 5,000 バイトを予約するには、varbinary(5000)
を使用します。varbinary(MAX)
では、最大ストレージ サイズ (約 2 GB) を使用できます。
バイナリ データをデータベースに直接保存する主な利点は、バイナリ データとデータベース レコードの間の密結合です。 これにより、バックアップや別のサイトまたはサーバーへのデータベースの移動など、データベース管理タスクが大幅に簡略化されます。 また、レコードを削除すると、対応するバイナリ データが自動的に削除されます。 また、バイナリ データをデータベースに保存することにはさらに小さな利点があります。 詳細については、「ASP.NET 2.0 を使用してデータベースにバイナリ ファイルを直接保存する」を参照してください。
Note
Microsoft SQL Server 2000 以前のバージョンでは、varbinary
データ型の上限は 8,000 バイトでした。 最大 2 GB のバイナリ データを保存するには、代わりに image
データ型 を使用する必要があります。 しかし、SQL Server 2005 での MAX
の追加により、image
データ型は非推奨となりました。 下位互換性のためにはまだサポートされていますが、Microsoft は、image
データ型が将来のバージョンの SQL Server で削除されることを発表しました。
より古いデータ モデルを操作している場合、image
データ型である可能性があります。 Northwind データベースの Categories
テーブルには、カテゴリの画像ファイルのバイナリ データを保存するために使用できる Picture
列があります。 Northwind データベースのルートは Microsoft Access と以前のバージョンの SQL Server にあるため、この列は image
型です。
このチュートリアルと次の 3 つのチュートリアルでは、両方の方法を使用します。 Categories
テーブルには、カテゴリの画像のバイナリ コンテンツを保存するための Picture
列が既に含まれています。 さらに列 (BrochurePath
) を追加して、PDF へのパスを Web サーバーのファイル システムに保存します。これを使用して、カテゴリの印刷品質の洗練された概要を提供できます。
手順 3: Categories
テーブルへの BrochurePath
列の追加
現在、Categories テーブルには、CategoryID
、CategoryName
、Description
、および Picture
の 4 つの列しかありません。 これらのフィールドに加えて、カテゴリのパンフレット (存在する場合) を指す新しいものを追加する必要があります。 この列を追加するには、サーバー エクスプローラーに移動し、Tables をドリルダウンし、Categories
テーブルを右クリックして、[テーブル定義を開く] を選択します (図 5 を参照)。 サーバー エクスプローラーが表示されない場合は、[表示] メニューから [サーバー エクスプローラー] オプションを選択して表示するか、Ctrl + Alt + S キーを押します。
BrochurePath
という名前の、NULL
を許可する、新しい varchar(200)
列を Categories
テーブルに追加し、[保存] アイコンをクリックします (または Ctrl + S キーを押します)。
図 5: Categories
テーブルに BrochurePath
列を追加する (クリックするとフルサイズの画像が表示されます)
手順 4: Picture
と BrochurePath
列を使用するためのアーキテクチャの更新
現在、データ アクセス層 (DAL) の CategoriesDataTable
には、CategoryID
、CategoryName
、Description
、NumberOfProducts
の 4 つの DataColumn
が定義されています。 「データ アクセス層を作成する」チュートリアルでこの DataTable を最初に設計したときは、CategoriesDataTable
には最初の 3 つの列しかありませんでした。NumberOfProducts
列は、「マスター レコードの箇条書きと詳細 DataList を使用してマスター/詳細を表示する」チュートリアルで追加されました。
「データ アクセス層を作成する」で説明したように、型指定された DataSet の DataTable によってビジネス オブジェクトが構成されます。 TableAdapter には、データベースと通信し、ビジネス オブジェクトにクエリ結果を設定する役割があります。 CategoriesDataTable
は、次の 3 つのデータ取得メソッドがある CategoriesTableAdapter
によって設定されます。
GetCategories()
では、TableAdapter のメイン クエリが実行され、Categories
テーブル内のすべてのレコードのCategoryID
、CategoryName
、およびDescription
フィールドが返されます。 メイン クエリは、自動生成されたInsert
およびUpdate
メソッドで使用されるものです。GetCategoryByCategoryID(categoryID)
では、CategoryID
が categoryID と等しいカテゴリのCategoryID
、CategoryName
、およびDescription
フィールドが返されます。GetCategoriesAndNumberOfProducts()
-Categories
テーブルのすべてのレコードのCategoryID
、CategoryName
、およびDescription
フィールドを返します。 また、サブクエリを使用して、各カテゴリに関連付けられている製品の数を返します。
これらのクエリのいずれも、Categories
テーブルの Picture
や BrochurePath
列を返さないことに注目してください。また、CategoriesDataTable
ではこれらのフィールドに DataColumn
が提供されません。 Picture および BrochurePath
プロパティを操作するには、最初にそれらを CategoriesDataTable
に追加してから、これらの列を返すように CategoriesTableAdapter
クラスを更新する必要があります。
Picture
と BrochurePath``DataColumn
の追加
まず、これら 2 つの列を CategoriesDataTable
に追加します。 CategoriesDataTable
のヘッダーを右クリックし、コンテキスト メニューから [追加] を選択し、[列] オプションを選びます。 これにより、Column1
という名前の新しい DataColumn
が DataTable に作成されます。 この列の名前を Picture
に変更します。 プロパティ ウィンドウで、DataColumn
の DataType
プロパティを System.Byte[]
に設定します (これはドロップダウン リストのオプションではありません。入力する必要があります)。
図 6: DataType
が System.Byte[]
のPicture
という名前の DataColumn
を作成する (クリックするとフルサイズの画像が表示されます)
DataTable にもう 1 つ DataColumn
を追加し、既定の DataType
値 (System.String
) を使用して BrochurePath
という名前を付けます。
TableAdapter から Picture
と BrochurePath
の値を返す
これら 2 つの DataColumn
が CategoriesDataTable
に追加されたので、CategoriesTableAdapter
を更新する準備ができました。 これらの両方の列値をメインの TableAdapter クエリで返すこともできますが、これにより、GetCategories()
メソッドが呼び出されるたびにバイナリ データが戻ります。 代わりに、メインの tableAdapter クエリを更新して BrochurePath
を戻し、特定のカテゴリの Picture
列を返す追加のデータ取得メソッドを作成しましょう。
メインの TableAdapter クエリを更新するには、CategoriesTableAdapter
のヘッダーを右クリックし、コンテキスト メニューから [構成] オプションを選択します。 これにより、TableAdapter 構成ウィザードが起動します。これは、過去の多くのチュートリアルで見てきたものです。 クエリを更新して BrochurePath
を戻し、[完了] をクリックします。
図 7: SELECT
ステートメントの列リストを更新して、BrochurePath
も返すようにする (クリックするとフルサイズの画像が表示されます)
TableAdapter にアドホック SQL ステートメントを使用するときに、メイン クエリの列リストを更新すると、TableAdapter のすべての SELECT
クエリ メソッドの列リストが更新されます。 つまり、GetCategoryByCategoryID(categoryID)
メソッドが更新され、BrochurePath
列が返されます。これは、意図したとおりである可能性があります。 しかし、GetCategoriesAndNumberOfProducts()
メソッドの列リストも更新され、各カテゴリの製品数を返すサブクエリが削除されました。 したがって、このメソッドの SELECT
クエリを更新する必要があります。 GetCategoriesAndNumberOfProducts()
メソッドを右クリックし、[構成] を選択し、SELECT
クエリを元の値に戻します。
SELECT CategoryID, CategoryName, Description,
(SELECT COUNT(*)
FROM Products p
WHERE p.CategoryID = c.CategoryID)
as NumberOfProducts
FROM Categories c
次に、特定のカテゴリの Picture
列値を返す新しい TableAdapter メソッドを作成します。 CategoriesTableAdapter
のヘッダーを右クリックし、[クエリの追加] オプションを選択して TableAdapter クエリ構成ウィザードを起動します。 このウィザードの最初の手順では、アドホック SQL ステートメント、新しいストアド プロシージャ、または既存のものを使用してデータのクエリを実行するかどうかが確認されます。 [SQL ステートメントを使用する] を選択して、[次へ] をクリックします。 行を返すので、2 番目の手順では [行を返す SELECT] オプションを選択します。
図 8: [SQL ステートメントを使用する] オプションを選択する (クリックするとフルサイズの画像が表示されます)
図 9: クエリで Categories テーブルからレコードが返されるので、[行を返す SELECT] を選択する (クリックするとフルサイズの画像が表示されます)
3 番目の手順では、次の SQL クエリを入力し、[次へ] をクリックします。
SELECT CategoryID, CategoryName, Description, BrochurePath, Picture
FROM Categories
WHERE CategoryID = @CategoryID
最後の手順では、新しいメソッドの名前を選択します。 DataTable を塗りつぶすパターンと GetCategoryWithBinaryDataByCategoryID
DataTable パターンを返す場合は、 と をそれぞれ使用FillCategoryWithBinaryDataByCategoryID
します。 [完了] をクリックして、ウィザードを完了します。
図 10: TableAdapter のメソッドの名前を選択する (クリックするとフルサイズの画像を表示されます)
Note
TableAdapter クエリ構成ウィザードを完了すると、新しいコマンド テキストがメイン クエリのスキーマとは異なるスキーマのデータを返すことを知らせるダイアログ ボックスが表示される場合があります。 つまり、TableAdapter のメイン クエリ GetCategories()
では、先ほど作成したものとは異なるスキーマが返されることがウィザードに示されます。 しかし、これは望んだことなので、このメッセージは無視してかまいません。
また、アドホック SQL ステートメントを使用していて、ウィザードを使って後で TableAdapter のメイン クエリを変更する場合は、メイン クエリの列だけを含むように GetCategoryWithBinaryDataByCategoryID
メソッドの SELECT
ステートメントの列リストが変更されることに注意してください (つまり、Picture
列がクエリから削除されます)。 この手順の前の GetCategoriesAndNumberOfProducts()
メソッドの場合と同様に、Picture
列を返すように列リストを手動で更新する必要があります。
2 つの DataColumn
を CategoriesDataTable
に追加し、GetCategoryWithBinaryDataByCategoryID
メソッドを CategoriesTableAdapter
に追加した後、型指定された DataSet デザイナーのこれらのクラスは、図 11 のスクリーンショットのようになるはずです。
図 11: DataSet デザイナーに新しい列とメソッドが含まれている
ビジネス ロジック層 (BLL) の更新
DAL が更新されたので、あとは、新しい CategoriesTableAdapter
メソッドのメソッドを含むようにビジネス ロジック層 (BLL) を拡張するだけです。 次のメソッドを CategoriesBLL
クラスに追加します:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable
GetCategoryWithBinaryDataByCategoryID(int categoryID)
{
return Adapter.GetCategoryWithBinaryDataByCategoryID(categoryID);
}
手順 5: クライアントから Web サーバーへのファイルのアップロード
バイナリ データを収集するときは、多くの場合、このデータはエンド ユーザーによって提供されます。 この情報をキャプチャするには、ユーザーが自分のコンピューターから Web サーバーにファイルをアップロードできる必要があります。 その後、アップロードされたデータをデータ モデルと統合する必要があります。これは、ファイルを Web サーバーのファイル システムに保存し、データベース内のファイルへのパスを追加することや、バイナリ コンテンツをデータベースに直接書き込むことを意味する場合があります。 この手順では、ユーザーが自分のコンピューターからサーバーにファイルをアップロードできるようにする方法を見ていきます。 次のチュートリアルでは、アップロードされたファイルとデータ モデルの統合に注目します。
ASP.NET 2.0 の新しい FileUpload Web コントロールでは、ユーザーが自分のコンピューターから Web サーバーにファイルを送信するためのメカニズムが提供されます。 FileUpload コントロールは、type
属性が file に設定されている <input>
要素としてレンダリングされ、ブラウザーは [参照] ボタンを含むテキスト ボックスとして表示されます。 [参照] ボタンをクリックすると、ユーザーがファイルを選択できるダイアログ ボックスが表示されます。 フォームがポストバックされると、選択されたファイルの内容がポストバックと共に送信されます。 サーバー側では、アップロードされたファイルに関する情報に、FileUpload コントロールのプロパティを使用してアクセスできます。
ファイルのアップロードを示すには、BinaryData
フォルダーの FileUpload.aspx
ページを開き、ツールボックスからデザイナーに FileUpload コントロールをドラッグし、コントロールの ID
プロパティを UploadTest
に設定します。 次に、ID
と Text
プロパティをそれぞれ UploadButton
と選択したファイルのアップロードに設定して、Button Web コントロールを追加します。 最後に、Button の下に Label Web コントロールを配置し、その Text
プロパティをクリアし、その ID
プロパティを UploadDetails
に設定します。
図 12: ASP.NET ページに FileUpload コントロールを追加する (クリックするとフルサイズの画像が表示されます)
図 13 は、ブラウザーで表示された場合のこのページを示しています。 [参照] ボタンをクリックすると、ファイルの選択ダイアログ ボックスが表示され、ユーザーは自分のコンピューターからファイルを選択できることに注意してください。 ファイルが選択されると、[選択したファイルのアップロード] ボタンをクリックすると、選択したファイルのバイナリ コンテンツを Web サーバーに送信するポストバックが発生します。
図 13: ユーザーは自分のコンピューターからサーバーにアップロードするファイルを選択できる (クリックするとフルサイズの画像が表示されます)
ポストバックでは、アップロードされたファイルをファイル システムに保存することも、そのバイナリ データを Stream 経由で直接操作することもできます。 この例では、~/Brochures
フォルダーを作成し、アップロードされたファイルをそこに保存します。 まず、Brochures
フォルダーをルート ディレクトリのサブフォルダーとしてサイトに追加します。 次に、UploadButton
の Click
イベントのイベント ハンドラーを作成し、次のコードを追加します。
protected void UploadButton_Click(object sender, EventArgs e)
{
if (UploadTest.HasFile == false)
{
// No file uploaded!
UploadDetails.Text = "Please first select a file to upload...";
}
else
{
// Display the uploaded file's details
UploadDetails.Text = string.Format(
@"Uploaded file: {0}<br />
File size (in bytes): {1:N0}<br />
Content-type: {2}",
UploadTest.FileName,
UploadTest.FileBytes.Length,
UploadTest.PostedFile.ContentType);
// Save the file
string filePath =
Server.MapPath("~/Brochures/" + UploadTest.FileName);
UploadTest.SaveAs(filePath);
}
}
FileUpload コントロールには、アップロードされたデータを操作するためのさまざまなプロパティが用意されています。 たとえば、HasFile
プロパティは、ファイルがユーザーによってアップロードされたかどうかを示しますが、FileBytes
プロパティでは、バイト配列としてアップロードされたバイナリ データへのアクセスが提供されます。 Click
イベント ハンドラーは、まず、ファイルがアップロードされていることを確かめます。 ファイルがアップロードされている場合、ラベルには、アップロードされたファイルの名前、サイズ (バイト単位)、およびコンテンツ タイプが示されます。
Note
ユーザーがファイルをアップロードしていることを確かめるために、HasFile
プロパティを確認し、false
の場合は警告を表示するか、代わりに RequiredFieldValidator コントロールを使用できます。
FileUpload の SaveAs(filePath)
では、アップロードされたファイルが指定された filePath に保存されます。 filePath virtual path (/Brochures/SomeFile.pdf
) ではなく、physical path (C:\Websites\Brochures\SomeFile.pdf
) である必要があります。 Server.MapPath(virtPath)
メソッドでは仮想パスを受け取り、対応する物理パスを返します。 ここでは、仮想パスは ~/Brochures/fileName
です。ここで、fileName はアップロードされたファイルの名前です。 仮想および物理パスと Server.MapPath
の使用の詳細については、「Server.MapPath メソッド」を参照してください。
Click
イベント ハンドラーが完了した後、少し時間を取ってブラウザーでページをテストします。 [参照] ボタンをクリックし、ハード ドライブからファイルを選択し、[選択したファイルのアップロード] ボタンをクリックします。 ポストバックでは、選択したファイルの内容が Web サーバーに送信され、ファイルに関する情報が表示されてから、~/Brochures
フォルダーに保存されます。 ファイルをアップロードした後、Visual Studio に戻り、ソリューション エクスプローラーで [更新] ボタンをクリックします。 先ほどアップロードファイルが ~/Brochures フォルダーに表示されるはずです。
図 14: ファイル EvolutionValley.jpg
が Web サーバーにアップロードされた (クリックするとフルサイズの画像が表示されます)
図 15: EvolutionValley.jpg
が ~/Brochures
フォルダーに保存された
アップロードしたファイルをファイル システムに保存する場合の微妙な点
Web サーバーのファイル システムにファイルをアップロードするときに対処する必要があるいくつかの微妙な点があります。 まず、セキュリティの問題があります。 ファイルをファイル システムに保存するには、ASP.NET ページが実行されているセキュリティ コンテキストに書き込みアクセス許可が必要です。 ASP.NET 開発 Web サーバーは、現在のユーザー アカウントのコンテキストで実行されます。 Web サーバーとして Microsoft のインターネット インフォメーション サービス (IIS) を使用している場合、セキュリティ コンテキストは IIS のバージョンとその構成によって異なります。
ファイル システムにファイルを保存する場合のもう 1 つの課題は、ファイルの名前付けに関するものです。 現在、このページでは、クライアントのコンピューター上のファイルと同じ名前を使用して、アップロードされたすべてのファイルを ~/Brochures
ディレクトリに保存します。 ユーザー A が Brochure.pdf
という名前のパンフレットをアップロードした場合、ファイルは ~/Brochure/Brochure.pdf
として保存されます。 しかし、後でユーザー B が同じファイル名 (Brochure.pdf
) を持つ別のパンフレット ファイルをアップロードした場合はどうなりますか? 現在のコードでは、ユーザー A のファイルがユーザー B がアップロードしたもので上書きされます。
ファイル名の競合を解決するためのいくつかの手法があります。 1 つのオプションは、同じ名前のものが既に存在する場合に、ファイルのアップロードを禁止することです。 この方法では、ユーザー B が Brochure.pdf
という名前のファイルをアップロードしようとすると、システムによってファイルは保存されず、代わりにファイル名を変更して再試行するようにユーザー B に通知するメッセージが表示されます。 もう 1 つの方法は、一意のファイル名を使用してファイルを保存することです。これは、グローバル一意識別子 (GUID) または対応するデータベース レコードの主キー列の値である可能性があります (アップロードがデータ モデルの特定の行に関連付けられている場合)。 次のチュートリアルでは、これらのオプションについて詳しく説明します。
大量のバイナリ データに関する課題
これらのチュートリアルでは、キャプチャされるバイナリ データのサイズが小さいことを前提としています。 数メガバイト以上の非常に大量のバイナリ データ ファイルを操作すると、これらのチュートリアルの範囲を超える新しい課題が発生します。 たとえば、既定では、ASP.NET で 4 MB を超えるアップロードが拒否されますが、これは Web.config
で <httpRuntime>
要素を使用して構成できます。 IIS では、独自のファイル アップロード サイズの制限も課されます。 さらに、大きなファイルのアップロードにかかった時間が、ASP.NET で要求を待機する既定の 110 秒を超える可能性があります。 大きなファイルを操作するときに発生するメモリとパフォーマンスの問題もあります。
FileUpload コントロールは、大きなファイルのアップロードでは実用的ではありません。 ファイルの内容がサーバーにポストされるため、エンド ユーザーは、アップロードが進行中であることを確認することなく、辛抱強く待つ必要があります。 これは、数秒でアップロードできる小さなファイルを処理する場合はそれほど問題ではありませんが、アップロードに数分かかる可能性のある大きなファイルを処理する場合に問題になる可能性があります。 大規模なアップロードの処理により適したさまざまなサードパーティのファイル アップロード コントロールがあり、これらのベンダーの多くは進行状況インジケーターと、より洗練されたユーザー エクスペリエンスを提供する ActiveX アップロード マネージャーを提供します。
アプリケーションで大きなファイルを処理する必要がある場合は、課題を慎重に調べ、特定のニーズに適したソリューションを見つける必要があります。
まとめ
バイナリ データをキャプチャする必要があるアプリケーションを構築すると、多くの課題が発生します。 このチュートリアルでは、最初の 2 つ (バイナリ データを保存する場所を決定すること、およびユーザーが Web ページを介してバイナリ コンテンツをアップロードできるようにすること) について調べました。 次の 3 つのチュートリアルでは、アップロードされたデータをデータベース内のレコードに関連付ける方法と、バイナリ データをそのテキスト データ フィールドと共に表示する方法を確認します。
プログラミングに満足!
もっと読む
この記事で説明したトピックの詳細については、次のリソースを参照してください。
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Teresa Murphy と Bernadette Leigh でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。