データ Web コントロールにバイナリ データを表示する (VB)
このチュートリアルでは、画像ファイルの表示や PDF ファイルの [ダウンロード] リンクの準備など、バイナリ データを Web ページに表示するオプションについて説明します。
はじめに
前のチュートリアルでは、バイナリ データをアプリケーションの基になるデータ モデルに関連付ける 2 つの手法を調べ、FileUpload コントロールを使用してブラウザーから Web サーバーのファイル システムにファイルをアップロードしました。 アップロードされたバイナリ データをデータ モデルに関連付ける方法はまだ確認していません。 つまり、ファイルをアップロードしてファイル システムに保存した後、ファイルへのパスを適切なデータベース レコードに格納する必要があります。 データがデータベースに直接格納されている場合は、アップロードされたバイナリ データをファイル システムに保存する必要はありませんが、データベースに挿入する必要があります。
ただし、データをデータ モデルに関連付ける前に、まず、バイナリ データをエンド ユーザーに提供する方法を見てみましょう。 テキスト データを表示するだけで十分ですが、バイナリ データはどのように表示する必要がありますか? もちろん、バイナリ データの種類によって異なります。 画像の場合は、画像を表示する必要があります。PDF、Microsoft Word ドキュメント、ZIP ファイル、およびその他の種類のバイナリ データの場合は、ダウンロード リンクを指定する方が適しています。
このチュートリアルでは、GridView や DetailsView などのデータ Web コントロールを使用して、バイナリ データを関連するテキスト データと共に表示する方法について説明します。 次のチュートリアルでは、アップロードしたファイルをデータベースに関連付けることに注目します。
手順 1: 値を指定するBrochurePath
Picture
テーブル内のCategories
列には、さまざまなカテゴリ イメージのバイナリ データが既に含まれています。 具体的には、各レコードの Picture
列には、粒度の低い、低品質の 16 色のビットマップ イメージのバイナリ コンテンツが保持されます。 各カテゴリ画像は幅 172 ピクセル、高さ 120 ピクセルで、約 11 KB を消費します。 さらに、列のバイナリ コンテンツには、イメージを Picture
表示する前に削除する必要がある 78 バイト の OLE ヘッダーが含まれています。 Northwind データベースには Microsoft Access にルートがあるため、このヘッダー情報が存在します。 Access では、バイナリ データは OLE Object データ型を使用して格納されます。このデータ型は、このヘッダーに付きます。 ここでは、画像を表示するために、これらの低品質の画像からヘッダーを削除する方法について説明します。 今後のチュートリアルでは、カテゴリの Picture
列を更新するためのインターフェイスを構築し、OLE ヘッダーを使用するビットマップ イメージを、不要な OLE ヘッダーなしで同等の JPG イメージに置き換えます。
前のチュートリアルでは、FileUpload コントロールの使用方法を確認しました。 そのため、Web サーバーのファイル システムにパンフレット ファイルを追加できます。 ただし、これを行っても、テーブル内の列はBrochurePath
Categories
更新されません。 次のチュートリアルでは、これを実現する方法について説明しますが、ここでは、この列の値を手動で指定する必要があります。
このチュートリアルのダウンロードでは、7 つの PDF パンフレット ファイルが ~/Brochures
フォルダー内にあります。1 つは、シーフードを除くカテゴリごとに 1 つです。 すべてのレコードにバイナリ データが関連付けられていないシナリオを処理する方法を示すために、シーフードパンフレットを追加することを意図的に省略しました。 これらの値でテーブルをCategories
更新するには、[サーバー エクスプローラー] からノードをCategories
右クリックし、[テーブル データの表示] を選択します。 次に、図 1 に示すように、パンフレットを含む各カテゴリのパンフレット ファイルへの仮想パスを入力します。 シーフード カテゴリのパンフレットはないため、 BrochurePath
列の値は のままに NULL
します。
図 1: テーブルの列の値をCategories
手動で入力する (フルサイズのBrochurePath
画像を表示する をクリックします)
手順 2: GridView でパンフレットのダウンロード リンクを提供する
テーブルに指定Categories
されたBrochurePath
値を使用して、カテゴリのパンフレットをダウンロードするためのリンクと共に各カテゴリを一覧表示する GridView を作成する準備ができました。 手順 4 では、この GridView を拡張して、カテゴリの画像も表示します。
まず、ツールボックスからフォルダー内のページのDisplayOrDownloadData.aspx
Designerに GridView をBinaryData
ドラッグします。 GridView の ID
スマート タグを使用して Categories
GridView を に設定し、新しいデータ ソースにバインドすることを選択します。 具体的には、オブジェクトの GetCategories()
メソッドを使用してデータを取得する という名前CategoriesDataSource
の ObjectDataSource にCategoriesBLL
バインドします。
図 2: 名前付きの CategoriesDataSource
新しい ObjectDataSource を作成する (フルサイズの画像を表示する場合はクリックします)
図 3: クラスを使用するように ObjectDataSource を構成する CategoriesBLL
(フルサイズの画像を表示するにはクリックします)
図 4: メソッドを使用してカテゴリの一覧を GetCategories()
取得する (フルサイズの画像を表示する をクリックします)
データ ソースの構成ウィザードが完了すると、Visual Studio によって、および BrochurePath
の BoundField が GridView CategoryID
NumberOfProducts
CategoryName
Description
にCategories
自動的に追加されます。DataColumn
メソッドのクエリではこの情報が NumberOfProducts
取得されないため、先に GetCategories()
進んで BoundField を削除してください。 また、BoundField を CategoryID
削除し、 CategoryName
プロパティと BrochurePath
BoundFields HeaderText
プロパティの名前をそれぞれ Category プロパティと Brochure プロパティに変更します。 これらの変更を行った後、GridView と ObjectDataSource の宣言型マークアップは次のようになります。
<asp:GridView ID="Categories" runat="server"
AutoGenerateColumns="False" DataKeyNames="CategoryID"
DataSourceID="CategoriesDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="CategoryName" HeaderText="Category"
SortExpression="CategoryName" />
<asp:BoundField DataField="Description" HeaderText="Description"
SortExpression="Description" />
<asp:BoundField DataField="BrochurePath" HeaderText="Brochure"
SortExpression="BrochurePath" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
ブラウザーでこのページを表示します (図 5 を参照)。 8 つのカテゴリのそれぞれが一覧表示されます。 値を持つ BrochurePath
7 つのカテゴリには、 BrochurePath
それぞれの BoundField に値が表示されます。 の値BrochurePath
をNULL
持つシーフードには、空のセルが表示されます。
図 5: 各カテゴリの名前、説明、および BrochurePath
値が一覧表示されている (フルサイズの画像を表示するをクリックします)
列の BrochurePath
テキストを表示するのではなく、パンフレットへのリンクを作成します。 これを行うには、BoundField を BrochurePath
削除し、HyperLinkField に置き換えます。 新しい HyperLinkField の HeaderText
プロパティを [パンフレット] に設定し、その Text
プロパティを [パンフレットの表示] に設定し、その DataNavigateUrlFields
プロパティを に BrochurePath
設定します。
図 6: の HyperLinkField を追加する BrochurePath
これにより、図 7 に示すように、GridView へのリンクの列が追加されます。 [パンフレットの表示] リンクをクリックすると、PDF リーダーがインストールされているかどうかとブラウザーの設定に応じて、PDF がブラウザーに直接表示されるか、ファイルのダウンロードを求められます。
図 7: カタログの表示リンクをクリックすると、カテゴリのパンフレットを表示できます (フルサイズの画像を表示する をクリックします)
図 8: カテゴリのパンフレット PDF が表示されている (フルサイズの画像を表示するをクリックします)
パンフレットのないカテゴリのビュー パンフレット テキストを非表示にする
図 7 に示すように、BrochurePath
HyperLinkField には、 に非NULL
値があるかどうかに関係なく、すべてのレコードのプロパティ値 BrochurePath
(パンフレットの表示) が表示されますText
。 もちろん、 が NULL
の場合BrochurePath
は、シーフード カテゴリの場合と同様に、リンクはテキストとしてのみ表示されます (図 7 を参照)。 [パンフレットの表示] というテキストを表示するのではなく、値のない BrochurePath
カテゴリに代替テキスト ([パンフレットなし] など) を表示すると便利な場合があります。
この動作を提供するには、値に基づいて適切な出力を出力するページ メソッドの呼び出しによってコンテンツが生成される TemplateField を使用する BrochurePath
必要があります。 最初に、 GridView コントロールの TemplateFields の使用 に関するチュートリアルで、この書式設定手法について確認しました。
HyperLinkField を選択し、[列の編集] ダイアログ ボックスの [このフィールドを BrochurePath
TemplateField に変換する] リンクをクリックして、HyperLinkField を TemplateField に変換します。
図 9: HyperLinkField を TemplateField に変換する
これにより、プロパティが値にバインドされている HyperLink Web コントロールを含む を持つ ItemTemplate
NavigateUrl
TemplateField が BrochurePath
作成されます。 このマークアップを メソッド GenerateBrochureLink
の呼び出しに置き換え、 の BrochurePath
値を渡します。
<asp:TemplateField HeaderText="Brochure">
<ItemTemplate>
<%# GenerateBrochureLink(Eval("BrochurePath")) %>
</ItemTemplate>
</asp:TemplateField>
次に、 を返String
し、 を入力パラメーターとして受け入れる という名前GenerateBrochureLink
のメソッドを、ASP.NET ページのObject
分離コード クラスに作成Protected
します。
Protected Function GenerateBrochureLink(BrochurePath As Object) As String
If Convert.IsDBNull(BrochurePath) Then
Return "No Brochure Available"
Else
Return String.Format("<a href="{0}">View Brochure</a>", _
ResolveUrl(BrochurePath.ToString()))
End If
End Function
このメソッドは、渡された Object
値がデータベース NULL
であるかどうかを判断し、存在する場合は、カテゴリにパンフレットがないことを示すメッセージを返します。 それ以外の場合は、値がある BrochurePath
場合はハイパーリンクで表示されます。 値が存在するBrochurePath
場合は、 メソッドにResolveUrl(url)
渡されることに注意してください。 このメソッドは、渡された URL を解決し、文字を ~
適切な仮想パスに置き換えます。 たとえば、アプリケーションが で/Tutorial55
ResolveUrl("~/Brochures/Meats.pdf")
ルート化されている場合、 は を返します/Tutorial55/Brochures/Meat.pdf
。
図 10 は、これらの変更が適用された後のページを示しています。 [シーフード カテゴリ] フィールドに BrochurePath
[パンフレットなし] というテキストが表示されるようになりました。
図 10: パンフレットのないカテゴリに対して利用可能なパンフレットがないテキストが表示される (フルサイズの画像を表示する をクリックします)
手順 3: カテゴリの画像を表示する Web ページを追加する
ユーザーは、ASP.NET ページにアクセスすると、ASP.NET ページの HTML を受け取ります。 受信した HTML は単なるテキストであり、バイナリ データは含まれません。 画像、サウンド ファイル、Macromedia Flash アプリケーション、埋め込みWindows メディア プレーヤービデオなどの追加のバイナリ データは、Web サーバー上に個別のリソースとして存在します。 HTML にはこれらのファイルへの参照が含まれていますが、ファイルの実際の内容は含まれません。
たとえば、HTML では、 要素は <img>
画像を参照するために使用され、 属性は src
次のように画像ファイルを指します。
<img src="MyPicture.jpg" ... />
ブラウザーは、この HTML を受信すると、イメージ ファイルのバイナリ コンテンツを取得するように Web サーバーに別の要求を行い、ブラウザーに表示します。 バイナリ データにも同じ概念が適用されます。 手順 2 では、パンフレットはページの HTML マークアップの一部としてブラウザーに送信されませんでした。 代わりに、レンダリングされた HTML はハイパーリンクを提供し、クリックするとブラウザーが PDF ドキュメントを直接要求する原因となったのです。
ユーザーがデータベース内に存在するバイナリ データを表示またはダウンロードできるようにするには、データを返す別の Web ページを作成する必要があります。 アプリケーションの場合、カテゴリの画像をデータベースに直接格納するバイナリ データ フィールドは 1 つだけです。 したがって、呼び出されると、特定のカテゴリの画像データを返すページが必要です。
という名前DisplayCategoryPicture.aspx
のフォルダーに新しい ASP.NET ページをBinaryData
追加します。 この場合は、[マスター ページの選択] チェック ボックスをオフのままにします。 このページでは、 CategoryID
querystring の値が想定され、そのカテゴリの Picture
列のバイナリ データが返されます。 このページはバイナリ データを返し、それ以外は何も返さないので、HTML セクションにマークアップは必要ありません。 そのため、左下隅にある [ソース] タブをクリックし、 ディレクティブを除くすべてのページマークアップを <%@ Page %>
削除します。 つまり、 DisplayCategoryPicture.aspx
宣言型マークアップは 1 行で構成する必要があります。
<%@ Page Language="VB" AutoEventWireup="true"
CodeFile="DisplayCategoryPicture.aspx.vb"
Inherits="BinaryData_DisplayCategoryPicture" %>
ディレクティブに 属性が表示された MasterPageFile
場合は <%@ Page %>
、それを削除します。
ページの分離コード クラスで、次のコードをイベント ハンドラーに Page_Load
追加します。
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim categoryID As Integer = _
Convert.ToInt32(Request.QueryString("CategoryID"))
' Get information about the specified category
Dim categoryAPI As New CategoriesBLL()
Dim categories As Northwind.CategoriesDataTable = _
categoryAPI.GetCategoryWithBinaryDataByCategoryID(categoryID)
Dim category As Northwind.CategoriesRow = categories(0)
' Output HTTP headers providing information about the binary data
Response.ContentType = "image/bmp"
' Output the binary data
' But first we need to strip out the OLE header
Const OleHeaderLength As Integer = 78
Dim strippedImageLength As Integer = _
category.Picture.Length - OleHeaderLength
Dim strippedImageData(strippedImageLength) As Byte
Array.Copy(category.Picture, OleHeaderLength, _
strippedImageData, 0, strippedImageLength)
Response.BinaryWrite(strippedImageData)
End Sub
このコードは、まず、querystring 値を CategoryID
という名前 categoryID
の変数に読み込むことから始めます。 次に、画像データは クラスの GetCategoryWithBinaryDataByCategoryID(categoryID)
メソッドの呼び出しをCategoriesBLL
介して取得されます。 このデータは メソッドを使用 Response.BinaryWrite(data)
してクライアントに返されますが、これを呼び出す前に、列値の OLE ヘッダーを Picture
削除する必要があります。 これを行うには、 という名前strippedImageData
のByte
配列を作成します。この配列は、列のPicture
文字数より正確に 78 文字少なくなります。 メソッドはArray.Copy
、位置 78 から にデータcategory.Picture
をコピーするためにstrippedImageData
使用されます。
プロパティは Response.ContentType
、返されるコンテンツの MIME の種類 を指定して、ブラウザーがそれをレンダリングする方法を認識できるようにします。 テーブルのCategories
Picture
列はビットマップ イメージであるため、ここではビットマップ MIME の種類 (image/bmp) が使用されます。 MIME の種類を省略しても、ほとんどのブラウザーでは、画像ファイルのバイナリ データの内容に基づいて型を推論できるため、画像が正しく表示されます。 ただし、可能であれば MIME の種類を含めるのが賢明です。 MIME メディアの種類の完全な一覧については、インターネット割り当て番号局の Web サイトを参照してください。
このページを作成すると、 にアクセスして特定のカテゴリの画像を DisplayCategoryPicture.aspx?CategoryID=categoryID
表示できます。 図 11 は、飲料カテゴリの画像を示しています。これは から DisplayCategoryPicture.aspx?CategoryID=1
表示できます。
図 11: 飲料カテゴリの画像が表示されている (フルサイズの画像を表示する をクリックします)
に DisplayCategoryPicture.aspx?CategoryID=categoryID
アクセスすると、'System.DBNull' 型のオブジェクトを 'System.Byte[]' 型にキャストできないという例外が発生します。この原因は 2 つあります。 まず、 Categories
テーブルの列で Picture
値が許可 NULL
されます。 ただし、ページには DisplayCategoryPicture.aspx
値以外NULL
の値が存在することを前提としています。 Picture
の プロパティに値があるNULL
場合は、 のプロパティCategoriesDataTable
に直接アクセスできません。 列の値Picture
を許可NULL
する場合は、次の条件を含めます。
If category.IsPictureNull() Then
' Display some "No Image Available" picture
Response.Redirect("~/Images/NoPictureAvailable.gif")
Else
' Send back the binary contents of the Picture column
' ... Set ContentType property and write out ...
' ... data via Response.BinaryWrite ...
End If
上記のコードでは、画像のないカテゴリにImages
対して表示するという名前NoPictureAvailable.gif
のイメージ ファイルがフォルダー内にあることを前提としています。
この例外は、s メソッドの GetCategoryWithBinaryDataByCategoryID
SELECT
ステートメントが メイン クエリの列リストに戻った場合CategoriesTableAdapter
にも発生する可能性があります。これは、アドホック SQL ステートメントを使用していて、TableAdapter の メイン クエリのウィザードを再実行した場合に発生する可能性があります。 メソッドの SELECT
ステートメントに列がまだGetCategoryWithBinaryDataByCategoryID
含まれていることをPicture
確認します。
注意
に DisplayCategoryPicture.aspx
アクセスするたびに、データベースにアクセスし、指定されたカテゴリの画像データが返されます。 ただし、ユーザーが最後に表示してからカテゴリの画像が変更されていない場合、これは無駄な作業です。 幸いなことに、HTTP では 条件付き GET が許可されます。 条件付き GET を使用すると、HTTP 要求を行うクライアントは、クライアントが Web サーバーからこのリソースをIf-Modified-Since
最後に取得した日時を提供する HTTP ヘッダーに沿って送信します。 この指定された日付以降にコンテンツが変更されていない場合、Web サーバーは 未変更状態コード (304) で応答し、要求されたリソースのコンテンツの送信を見送る可能性があります。 つまり、この手法を使用すると、クライアントが最後にアクセスしてから変更されていない場合に、Web サーバーがリソースのコンテンツを返送する必要が解消されます。
ただし、この動作を実装するには、列が最後に更新されたときにPicture
キャプチャするCategories
列と、ヘッダーのチェックするコードをテーブルに追加PictureLastModified
するIf-Modified-Since
必要があります。 ヘッダーと条件付き GET ワークフローの If-Modified-Since
詳細については、「 HTTP Conditional GET for RSS Hackers 」および「 ASP.NET ページでの HTTP 要求の実行の詳細」を参照してください。
手順 4: GridView でカテゴリ画像を表示する
特定のカテゴリの画像を表示する Web ページが作成されたので、 Image Web コントロール または を指す HTML <img>
要素を DisplayCategoryPicture.aspx?CategoryID=categoryID
使用して表示できます。 データベース データによって URL が決定されたイメージは、ImageField を使用して GridView または DetailsView に表示できます。 ImageField には、DataImageUrlField
HyperLinkField DataNavigateUrlFields
とDataImageUrlFormatString
プロパティと同様に機能する プロパティと DataNavigateUrlFormatString
プロパティが含まれています。
では、ImageField を Categories
追加して GridView DisplayOrDownloadData.aspx
を拡張し、各カテゴリの画像を表示してみましょう。 ImageField を追加し、その DataImageUrlField
プロパティと DataImageUrlFormatString
プロパティをそれぞれ と DisplayCategoryPicture.aspx?CategoryID={0}
にCategoryID
設定するだけです。 これにより、属性が を参照DisplayCategoryPicture.aspx?CategoryID={0}
する要素src
を<img>
レンダリングする GridView 列が作成されます。ここで{0}、 は GridView 行のCategoryID
値に置き換えられます。
図 12: GridView に ImageField を追加する
ImageField を追加すると、GridView の宣言型構文は次のようになるはずです。
<asp:GridView ID="Categories" runat="server" AutoGenerateColumns="False"
DataKeyNames="CategoryID" DataSourceID="CategoriesDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CategoryName" HeaderText="Category"
SortExpression="CategoryName" />
<asp:BoundField DataField="Description" HeaderText="Description"
SortExpression="Description" />
<asp:TemplateField HeaderText="Brochure">
<ItemTemplate>
<%# GenerateBrochureLink(Eval("BrochurePath")) %>
</ItemTemplate>
</asp:TemplateField>
<asp:ImageField DataImageUrlField="CategoryID"
DataImageUrlFormatString="DisplayCategoryPicture.aspx?CategoryID={0}">
</asp:ImageField>
</Columns>
</asp:GridView>
ブラウザーからこのページを表示するには、少し時間を取ります。 各レコードにカテゴリの画像が含まれるようになったことに注意してください。
図 13: 各行のカテゴリの図が表示されます (フルサイズの画像を表示する をクリックします)。
まとめ
このチュートリアルでは、バイナリ データを表示する方法について説明しました。 データの表示方法は、データの種類によって異なります。 PDF パンフレット ファイルの場合、クリックするとユーザーを PDF ファイルに直接移動する [パンフレットの表示] リンクをユーザーに提供しました。 カテゴリの図では、まずデータベースからバイナリ データを取得して返すページを作成し、そのページを使用して各カテゴリの画像を GridView に表示しました。
バイナリ データを表示する方法を確認したので、バイナリ データを使用してデータベースに対して挿入、更新、および削除を実行する方法を確認する準備ができました。 次のチュートリアルでは、アップロードしたファイルを対応するデータベース レコードに関連付ける方法について説明します。 その後のチュートリアルでは、既存のバイナリ データを更新する方法と、関連するレコードが削除されたときにバイナリ データを削除する方法について説明します。
幸せなプログラミング!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、 4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・自分自身 ASP.NET 24時間で2.0です。 にアクセスmitchell@4GuysFromRolla.comすることも、ブログを介して アクセスすることもできます。これは でhttp://ScottOnWriting.NET確認できます。
特別な感謝
このチュートリアル シリーズは、多くの役立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、テレサ マーフィーと Dave Gardner でした。 今後の MSDN 記事の確認に関心がありますか? その場合は、 に行mitchell@4GuysFromRolla.comをドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示