SQL Server に FILESTREAM で登録されている画像を ASP.NET のListView で並べて表示する
到達点
表題のとおり
準備
画像を格納するテーブル「TMDbPoster」には、あらかじめ列「Image」に画像を登録しておいた。どうやって登録したかは後日別記事で。
テーブル作成
CREATE TABLE [dbo].[TMDbPoster](
[ID] [int] IDENTITY(1,1) NOT NULL,
[STREAMID] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[TMDbID] [int] NULL,
[aspect_ratio] [numeric](3, 2) NULL,
[file_path] [nvarchar](256) NULL,
[height] [int] NULL,
[width] [int] NULL,
[iso_639_1] [nvarchar](50) NULL,
[vote_average] [numeric](18, 14) NULL,
[vote_count] [int] NULL,
[Image] [varbinary](max) FILESTREAM NULL,
CONSTRAINT [PK_TMDbPoster] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1],
CONSTRAINT [UQ__TMDbPost__3214EC266F70E2A6] UNIQUE NONCLUSTERED
(
[STREAMID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1]
[ID] [int] IDENTITY(1,1) NOT NULL,
[STREAMID] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[TMDbID] [int] NULL,
[aspect_ratio] [numeric](3, 2) NULL,
[file_path] [nvarchar](256) NULL,
[height] [int] NULL,
[width] [int] NULL,
[iso_639_1] [nvarchar](50) NULL,
[vote_average] [numeric](18, 14) NULL,
[vote_count] [int] NULL,
[Image] [varbinary](max) FILESTREAM NULL,
CONSTRAINT [PK_TMDbPoster] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1],
CONSTRAINT [UQ__TMDbPost__3214EC266F70E2A6] UNIQUE NONCLUSTERED
(
[STREAMID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] FILESTREAM_ON [FileStreamGroup1]
完成イメージ
ASP.NET の ListView で、SQL Serverに登録されているバイナリ画像を並べて表示する。
テキストボックスに入力した縦横サイズに応じて、バイナリーデータから画像を描画する。
コード
ListViewPoster.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ListViewPoster.aspx.vb" Inherits="ListViewPoster" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
W:<asp:TextBox ID="TextBoxW" runat="server" Columns="4">150</asp:TextBox>
H:<asp:TextBox ID="TextBoxH" runat="server" Columns="4">300</asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" DataSourceID="SqlDataSource1" GroupItemCount="10">
<AlternatingItemTemplate>
<td runat="server" style="vertical-align: top">ID:
<asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
<br />STREAMID:
<asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' Visible="False" />
<br />TMDbID:
<asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
<br />aspect_ratio:
<asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
<br />file_path:
<asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' Visible="False" />
<br />height:
<asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
<br />width:
<asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
<br />
<asp:Image ID="Image2" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' />
<br /></td>
</AlternatingItemTemplate>
<EditItemTemplate>
<td runat="server" style="">ID:
<asp:Label ID="IDLabel1" runat="server" Text='<%# Eval("ID") %>' />
<br />STREAMID:
<asp:TextBox ID="STREAMIDTextBox" runat="server" Text='<%# Bind("STREAMID") %>' />
<br />TMDbID:
<asp:TextBox ID="TMDbIDTextBox" runat="server" Text='<%# Bind("TMDbID") %>' />
<br />aspect_ratio:
<asp:TextBox ID="aspect_ratioTextBox" runat="server" Text='<%# Bind("aspect_ratio") %>' />
<br />file_path:
<asp:TextBox ID="file_pathTextBox" runat="server" Text='<%# Bind("file_path") %>' />
<br />height:
<asp:TextBox ID="heightTextBox" runat="server" Text='<%# Bind("height") %>' />
<br />width:
<asp:TextBox ID="widthTextBox" runat="server" Text='<%# Bind("width") %>' />
<br />iso_639_1:
<asp:TextBox ID="iso_639_1TextBox" runat="server" Text='<%# Bind("iso_639_1") %>' />
<br />vote_average:
<asp:TextBox ID="vote_averageTextBox" runat="server" Text='<%# Bind("vote_average") %>' />
<br />vote_count:
<asp:TextBox ID="vote_countTextBox" runat="server" Text='<%# Bind("vote_count") %>' />
<br />
<asp:Button ID="UpdateButton" runat="server" CommandName="Update" Text="" />
<br />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="" />
<br /></td>
</EditItemTemplate>
<EmptyDataTemplate>
<table runat="server" style="">
<tr>
<td></td>
</tr>
</table>
</EmptyDataTemplate>
<EmptyItemTemplate>
<td runat="server" />
</EmptyItemTemplate>
<GroupTemplate>
<tr id="itemPlaceholderContainer" runat="server">
<td id="itemPlaceholder" runat="server"></td>
</tr>
</GroupTemplate>
<InsertItemTemplate>
<td runat="server" style="">STREAMID:
<asp:TextBox ID="STREAMIDTextBox" runat="server" Text='<%# Bind("STREAMID") %>' />
<br />TMDbID:
<asp:TextBox ID="TMDbIDTextBox" runat="server" Text='<%# Bind("TMDbID") %>' />
<br />aspect_ratio:
<asp:TextBox ID="aspect_ratioTextBox" runat="server" Text='<%# Bind("aspect_ratio") %>' />
<br />file_path:
<asp:TextBox ID="file_pathTextBox" runat="server" Text='<%# Bind("file_path") %>' />
<br />height:
<asp:TextBox ID="heightTextBox" runat="server" Text='<%# Bind("height") %>' />
<br />width:
<asp:TextBox ID="widthTextBox" runat="server" Text='<%# Bind("width") %>' />
<br />iso_639_1:
<asp:TextBox ID="iso_639_1TextBox" runat="server" Text='<%# Bind("iso_639_1") %>' />
<br />vote_average:
<asp:TextBox ID="vote_averageTextBox" runat="server" Text='<%# Bind("vote_average") %>' />
<br />vote_count:
<asp:TextBox ID="vote_countTextBox" runat="server" Text='<%# Bind("vote_count") %>' />
<br />
<asp:Button ID="InsertButton" runat="server" CommandName="Insert" Text="" />
<br />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="" />
<br /></td>
</InsertItemTemplate>
<ItemTemplate>
<td runat="server" style="vertical-align: top">ID:
<asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
<br />STREAMID:
<asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' Visible="False" />
<br />TMDbID:
<asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
<br />aspect_ratio:
<asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
<br />file_path:
<asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' Visible="False" />
<br />height:
<asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
<br />width:
<asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
<br />
<asp:Image ID="Image1" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' />
<br /></td>
</ItemTemplate>
<LayoutTemplate>
<table runat="server">
<tr runat="server">
<td runat="server">
<table id="groupPlaceholderContainer" runat="server" border="0" style="">
<tr id="groupPlaceholder" runat="server">
</tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server" style="">
<asp:DataPager ID="DataPager1" runat="server" PageSize="20">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />
<asp:NumericPagerField ButtonCount="50" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
<SelectedItemTemplate>
<td runat="server" style="">ID:
<asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
<br />STREAMID:
<asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' />
<br />TMDbID:
<asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
<br />aspect_ratio:
<asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
<br />file_path:
<asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' />
<br />height:
<asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
<br />width:
<asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
<br />iso_639_1:
<asp:Label ID="iso_639_1Label" runat="server" Text='<%# Eval("iso_639_1") %>' />
<br />vote_average:
<asp:Label ID="vote_averageLabel" runat="server" Text='<%# Eval("vote_average") %>' />
<br />vote_count:
<asp:Label ID="vote_countLabel" runat="server" Text='<%# Eval("vote_count") %>' />
<br /></td>
</SelectedItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [ID], [STREAMID], [TMDbID], [aspect_ratio], [file_path], [height], [width], [iso_639_1], [vote_average], [vote_count],@w as w,@h as h FROM [TMDbPoster]">
<SelectParameters>
<asp:ControlParameter ControlID="TextBoxW" Name="w" PropertyName="Text" />
<asp:ControlParameter ControlID="TextBoxH" Name="h" PropertyName="Text" />
</SelectParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
Imageコントロールの ImageUrl プロパティに imagePoster.aspx?ID=n&w=幅&h=高さ を設定することで、imagePoster.aspx で描画された画像が表示される。データベースから読み込んだID、テキストボックスに入力されたw、h という3つの値からURLパラメータを生成するところで悩んだ。DataBinder を使って、ListView が読み込んだデータの複数の項目を連結すればいいみたい。
URLパラメータの生成部分
<asp:Image ID="Image1" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' />
ListViewPoster.aspx ※コードはない
Partial Class ListViewPoster
Inherits System.Web.UI.Page
End Class
Inherits System.Web.UI.Page
End Class
imagePoster.aspx ではURLパラメータから受け取った ID で TMDbPoster からデータを読んで、縦横ピクセルの値により画像を描画する。
imagePoster.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="imagePoster.aspx.vb" Inherits="imagePoster" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [Image] FROM [TMDbPoster] WHERE ([ID] = @ID)">
<SelectParameters>
<asp:QueryStringParameter Name="ID" QueryStringField="ID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [Image] FROM [TMDbPoster] WHERE ([ID] = @ID)">
<SelectParameters>
<asp:QueryStringParameter Name="ID" QueryStringField="ID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
imagePoster.aspx
Partial Class imagePoster
Inherits System.Web.UI.Page
Protected Sub Page_PreLoad(sender As Object, e As EventArgs) Handles Me.PreLoad
Dim dv As Data.DataView = SqlDataSource1.Select(DataSourceSelectArguments.Empty)
If Not dv Is Nothing Then
If dv.Table.Rows.Count > 0 Then
If Not IsDBNull(dv.Table.Rows(0)(0)) Then
Dim oW As Integer = Page.Request.QueryString.Get("w")
Dim oH As Integer = Page.Request.QueryString.Get("h")
Dim bmp As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(New System.IO.MemoryStream(DirectCast(dv.Table.Rows(0)(0), Byte())))
If bmp.Width > oW Or bmp.Height > oH Then
Dim s As Double = Math.Min(oW / bmp.Width, oH / bmp.Height)
Dim sW As Integer = CInt(s * bmp.Width)
Dim sH As Integer = CInt(s * bmp.Height)
Dim outBmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(sW, sH)
Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(outBmp)
g.DrawImage(bmp, 0, 0, sW, sH)
End Using
outBmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Else
Response.BinaryWrite(DirectCast(dv.Table.Rows(0)(0), Byte()))
End If
Response.End()
End If
End If
End If
End Sub
End Class
Inherits System.Web.UI.Page
Protected Sub Page_PreLoad(sender As Object, e As EventArgs) Handles Me.PreLoad
Dim dv As Data.DataView = SqlDataSource1.Select(DataSourceSelectArguments.Empty)
If Not dv Is Nothing Then
If dv.Table.Rows.Count > 0 Then
If Not IsDBNull(dv.Table.Rows(0)(0)) Then
Dim oW As Integer = Page.Request.QueryString.Get("w")
Dim oH As Integer = Page.Request.QueryString.Get("h")
Dim bmp As System.Drawing.Bitmap = System.Drawing.Bitmap.FromStream(New System.IO.MemoryStream(DirectCast(dv.Table.Rows(0)(0), Byte())))
If bmp.Width > oW Or bmp.Height > oH Then
Dim s As Double = Math.Min(oW / bmp.Width, oH / bmp.Height)
Dim sW As Integer = CInt(s * bmp.Width)
Dim sH As Integer = CInt(s * bmp.Height)
Dim outBmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(sW, sH)
Using g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(outBmp)
g.DrawImage(bmp, 0, 0, sW, sH)
End Using
outBmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Else
Response.BinaryWrite(DirectCast(dv.Table.Rows(0)(0), Byte()))
End If
Response.End()
End If
End If
End If
End Sub
End Class
コメント
コメントを投稿