ユーザーがバイナリ ファイル (Word や PDF ドキュメントなど) を Web サイトにアップロードし、サーバーのファイル システムまたはデータベースに保存できるようにする方法について学習します。
はじめに
これまでに調べたすべてのチュートリアルでは、テキスト データのみを操作してきました。 しかし、多くのアプリケーションには、テキスト データとバイナリ データの両方をキャプチャするデータ モデルがあります。 オンライン出会い系サイトでは、ユーザーが自分のプロファイルに関連付ける写真をアップロードできる場合があります。 求人 Web サイトでは、ユーザーが履歴書を Microsoft Word または PDF ドキュメントとしてアップロードできる場合があります。
バイナリ データを操作する場合、さらに新たな一連の課題が発生します。 バイナリ データをアプリケーションに保存する方法を決定する必要があります。 新しいレコードの挿入に使用されるインターフェイスは、ユーザーが自分のコンピューターからファイルをアップロードできるように更新する必要があります。また、レコードの関連付けられているバイナリ データをダウンロードするための手段を表示または提供するための追加の手順を行う必要があります。 このチュートリアルと次の 3 つのチュートリアルでは、これらの課題を乗り越える方法について調べます。 これらのチュートリアルの最後に、写真と PDF パンフレットを各カテゴリに関連付ける完全に機能するアプリケーションを構築することになります。 この特定のチュートリアルでは、バイナリ データを保存するためのさまざまな手法を確認し、ユーザーが自分のコンピューターからファイルをアップロードし、Web サーバーのファイル システムに保存できるようにする方法について調べます。
注
アプリケーションのデータ モデルの一部であるバイナリ データは、バイナリ ラージ 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: バイナリ Data-Related チュートリアルの ASP.NET ページを追加する
他のフォルダーと同様に、Default.aspx
フォルダーの BinaryData
のセクションにチュートリアルが一覧表示されます。
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
テーブルにパスを記録することです。 この方法では、おそらく、ImagePath
型の Products
テーブルに varchar(200)
列を追加します。 ユーザーがチャイの写真をアップロードすると、その写真は Web サーバーのファイル システム (~/Images/Tea.jpg
) に保存される可能性があります。ここで、~
はアプリケーションの物理パスを表します。 つまり、Web サイトが物理パス C:\Websites\Northwind\
でルート化されている場合、~/Images/Tea.jpg
は C:\Websites\Northwind\Images\Tea.jpg
と同等になります。 画像ファイルをアップロードした後、Products
テーブルのチャイ レコードを更新して、ImagePath
列で新しい画像のパスが参照されるようにします。 すべての製品画像をアプリケーションの ~/Images/Tea.jpg
フォルダーに配置することにした場合、Tea.jpg
または単に Images
を使用することができます。
バイナリ データをファイル システムに保存する主な利点は次のとおりです。
- 簡単に説明しますが、データベース内に直接格納されているバイナリ データの格納と取得には、ファイル システムを介してデータを操作する場合よりも少し多くのコードが必要です。 さらに、ユーザーがバイナリ データを表示またはダウンロードするには、そのデータの 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 を使用したデータベースへのバイナリ ファイルの直接格納 」を参照してください。
注
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: BrochurePath
テーブルへの Categories
列の追加
現在、Categories テーブルには、CategoryID
、CategoryName
、Description
、および Picture
の 4 つの列しかありません。 これらのフィールドに加えて、カテゴリのパンフレット (存在する場合) を指す新しいものを追加する必要があります。 この列を追加するには、サーバー エクスプローラーに移動し、Tables をドリルダウンし、Categories
テーブルを右クリックして、[テーブル定義を開く] を選択します (図 5 を参照)。 サーバー エクスプローラーが表示されない場合は、[表示] メニューから [サーバー エクスプローラー] オプションを選択して表示するか、Ctrl + Alt + S キーを押します。
varchar(200)
という名前の、Categories
を許可する、新しい BrochurePath
列を NULL
テーブルに追加し、[保存] アイコンをクリックします (または Ctrl + S キーを押します)。
図 5: BrochurePath
テーブルにCategories
列を追加する (フルサイズの画像を表示する をクリックします)。
手順 4: Picture
と BrochurePath
列を使用するためのアーキテクチャの更新
現在、データ アクセス層 (DAL) の CategoriesDataTable
には、DataColumn
、CategoryID
、CategoryName
、Description
の 4 つの NumberOfProducts
が定義されています。 データ アクセス層の作成 チュートリアルでこの DataTable を最初に設計したとき、 CategoriesDataTable
には最初の 3 つの列しかありませんでした。 NumberOfProducts
列は、 詳細 DataList チュートリアルでマスター レコードの箇条書きリストを使用してマスター/詳細 に追加されました。
「データ アクセス層の作成」で説明したように、型指定された DataSet の DataTable はビジネス オブジェクトを構成します。 TableAdapter には、データベースと通信し、ビジネス オブジェクトにクエリ結果を設定する役割があります。
CategoriesDataTable
は、次の 3 つのデータ取得メソッドがある CategoriesTableAdapter
によって設定されます。
-
GetCategories()
では、TableAdapter のメイン クエリが実行され、CategoryID
テーブル内のすべてのレコードのCategoryName
、Description
、およびCategories
フィールドが返されます。 メイン クエリは、自動生成されたInsert
およびUpdate
メソッドで使用されるものです。 -
GetCategoryByCategoryID(categoryID)
は、CategoryID
がCategoryName
と等しいカテゴリのDescription
、CategoryID
、およびフィールドを返します。 -
GetCategoriesAndNumberOfProducts()
-CategoryID
テーブルのすべてのレコードのCategoryName
、Description
、およびCategories
フィールドを返します。 また、サブクエリを使用して、各カテゴリに関連付けられている製品の数を返します。
これらのクエリのいずれも、Categories
テーブルの Picture
や BrochurePath
列を返さないことに注目してください。また、CategoriesDataTable
ではこれらのフィールドに DataColumn
が提供されません。 Picture および BrochurePath
プロパティを操作するには、最初にそれらを CategoriesDataTable
に追加してから、これらの列を返すように CategoriesTableAdapter
クラスを更新する必要があります。
Picture
と BrochurePath``DataColumn
の追加
まず、これら 2 つの列を CategoriesDataTable
に追加します。
CategoriesDataTable
のヘッダーを右クリックし、コンテキスト メニューから [追加] を選択し、[列] オプションを選びます。 これにより、DataColumn
という名前の新しい Column1
が DataTable に作成されます。 この列の名前を Picture
に変更します。 プロパティ ウィンドウで、DataColumn
の DataType
プロパティを System.Byte[]
に設定します (これはドロップダウン リストのオプションではありません。入力する必要があります)。
図 6: DataColumn
がPicture
である名前付きDataType
System.Byte[]
を作成する (画像をフルサイズで表示するにはクリックしてください)
DataTable にもう 1 つ DataColumn
を追加し、既定の BrochurePath
値 (DataType
) を使用して System.String
という名前を付けます。
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: クエリはカテゴリ テーブルからレコードを返すので、行を返す SELECT を選択します (フルサイズの画像を表示する 場合はクリックします)
3 番目の手順では、次の SQL クエリを入力し、[次へ] をクリックします。
SELECT CategoryID, CategoryName, Description, BrochurePath, Picture
FROM Categories
WHERE CategoryID = @CategoryID
最後の手順では、新しいメソッドの名前を選択します。 DataTable を塗りつぶすパターンと FillCategoryWithBinaryDataByCategoryID
DataTable パターンを返す場合は、 と をそれぞれ使用GetCategoryWithBinaryDataByCategoryID
します。 [完了] をクリックして、ウィザードを完了します。
図 10: TableAdapter のメソッドの名前を選択します (フルサイズの画像を表示する をクリックします)。
注
TableAdapter クエリ構成ウィザードを完了すると、新しいコマンド テキストがメイン クエリのスキーマとは異なるスキーマのデータを返すことを知らせるダイアログ ボックスが表示される場合があります。 つまり、TableAdapter のメイン クエリ GetCategories()
では、先ほど作成したものとは異なるスキーマが返されることがウィザードに示されます。 しかし、これは望んだことなので、このメッセージは無視してかまいません。
また、アドホック SQL ステートメントを使用していて、ウィザードを使って後で TableAdapter のメイン クエリを変更する場合は、メイン クエリの列だけを含むように GetCategoryWithBinaryDataByCategoryID
メソッドの SELECT
ステートメントの列リストが変更されることに注意してください (つまり、Picture
列がクエリから削除されます)。 この手順の前の Picture
メソッドの場合と同様に、GetCategoriesAndNumberOfProducts()
列を返すように列リストを手動で更新する必要があります。
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 コントロールは、<input>
属性が file に設定されている type
要素としてレンダリングされ、ブラウザーは [参照] ボタンを含むテキスト ボックスとして表示されます。 [参照] ボタンをクリックすると、ユーザーがファイルを選択できるダイアログ ボックスが表示されます。 フォームがポストバックされると、選択されたファイルの内容がポストバックと共に送信されます。 サーバー側では、アップロードされたファイルに関する情報に、FileUpload コントロールのプロパティを使用してアクセスできます。
ファイルのアップロードを示すには、FileUpload.aspx
フォルダーの BinaryData
ページを開き、ツールボックスからデザイナーに 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
イベント ハンドラーは、まず、ファイルがアップロードされていることを確かめます。 ファイルがアップロードされている場合、ラベルには、アップロードされたファイルの名前、サイズ (バイト単位)、およびコンテンツ タイプが示されます。
注
ユーザーがファイルを確実にアップロードできるようにするには、 HasFile
プロパティを確認し、 false
場合は警告を表示するか、代わりに RequiredFieldValidator コントロール を使用できます。
FileUpload SaveAs(filePath)
は、アップロードしたファイルを指定した filePath に保存します。
filePath は、仮想パス (C:\Websites\Brochures\SomeFile.pdf
) ではなく物理パス (/Brochures/SomeFile.pdf
) である必要があります。
Server.MapPath(virtPath)
メソッドは仮想パスを受け取り、対応する物理パスを返します。 ここでは、仮想パスは ~/Brochures/fileName
。 fileName はアップロードされたファイルの名前です。 仮想パスと物理パスの詳細との使用については、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 を超えるアップロードを拒否しますが、<httpRuntime>
のWeb.config
を使用して構成できます。 IIS では、独自のファイル アップロード サイズの制限も課されます。 さらに、大きなファイルのアップロードにかかった時間が、ASP.NET で要求を待機する既定の 110 秒を超える可能性があります。 大きなファイルを操作するときに発生するメモリとパフォーマンスの問題もあります。
FileUpload コントロールは、大きなファイルのアップロードでは実用的ではありません。 ファイルの内容がサーバーにポストされるため、エンド ユーザーは、アップロードが進行中であることを確認することなく、辛抱強く待つ必要があります。 これは、数秒でアップロードできる小さなファイルを処理する場合はそれほど問題ではありませんが、アップロードに数分かかる可能性のある大きなファイルを処理する場合に問題になる可能性があります。 大規模なアップロードの処理により適したさまざまなサードパーティのファイル アップロード コントロールがあり、これらのベンダーの多くは進行状況インジケーターと、より洗練されたユーザー エクスペリエンスを提供する ActiveX アップロード マネージャーを提供します。
アプリケーションで大きなファイルを処理する必要がある場合は、課題を慎重に調べ、特定のニーズに適したソリューションを見つける必要があります。
まとめ
バイナリ データをキャプチャする必要があるアプリケーションを構築すると、多くの課題が発生します。 このチュートリアルでは、最初の 2 つ (バイナリ データを保存する場所を決定すること、およびユーザーが Web ページを介してバイナリ コンテンツをアップロードできるようにすること) について調べました。 次の 3 つのチュートリアルでは、アップロードされたデータをデータベース内のレコードに関連付ける方法と、バイナリ データをそのテキスト データ フィールドと共に表示する方法を確認します。
プログラミングに満足!
もっと読む
この記事で説明したトピックの詳細については、次のリソースを参照してください。
- Large-Value データ型の使用
- FileUpload コントロールのクイック スタート
- ASP.NET 2.0 FileUpload サーバー コントロール
- ファイルアップロードのダークサイド
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Teresa Murphy と Bernadette Leigh でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.comにご連絡ください。