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]

データは全部で6779件ある。
05

 

完成イメージ

ASP.NET の ListView で、SQL Serverに登録されているバイナリ画像を並べて表示する。
0102

テキストボックスに入力した縦横サイズに応じて、バイナリーデータから画像を描画する。
0304

 

 

コード

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

 

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>
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

コメント

このブログの人気の投稿

ダブルクォーテーションで括られたCSVカ​ンマ区切りテキストファイルを SQL Server で Bulk Insert する方法

PowerShellでTSV/CSVの列を絞り込んで抽出し、(先頭/行末)からN行出力する

IKEAの鏡を壁に取り付ける