SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする
目的
SQLServerのテーブル TMDbPosters に映画のポスター画像をバイナリ(VARBINARY)で保存している。これを指定するフォルダに画像ファイルとしてエクスポートする。
ポスター画像がバイナリで登録されているテーブル「TMDbPosters」
- 列「ImageはVARBINARY(MAX)でポスター画像を格納している。
- 列「file_Path」はバイナリ登録前のポスター画像のファイル名。
完成イメージ
ポスター画像をListView で表示するのは SQL Server に FILESTREAM で登録されている画像を ASP.NET のListView で並べて表示する を参照。これをベースに作成した。
W:ポスターの横幅
H:ポスターの高さ
ボタン「Display」:W、Hで指定したサイズでポスターを再描画する
ボタン「Export」:表示されている画像を画像ファイルとしてエクスポートする
ボタン「ExportAll」:テーブルに格納されている全画像を画像ファイルとしてエクスポートする
動作
「Export」をクリックすると、ListView に表示されているポスターが、Web.Config で指定したフォルダにエクスポートされる。
→
↓
↓
Web.Config
<?xml version="1.0"?>
<!--
ASP.NET
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="TESTConnectionString" connectionString="Data Source=SN78SH7;Initial Catalog=TEST;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<httpRuntime targetFramework="4.5"/>
</system.web>
<appSettings>
<add key="ImageURL" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/"/>
<add key="ImageURLW150" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w150"/>
<add key="ImageURLW300" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w300"/>
<add key="ImageURLW600" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w600"/>
<add key="ImageURLW1280" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w1280"/>
<add key="ImageURLOriginal" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/original"/>
<add key="ImageTMDbPosterFolder" value="D:\TMDbPoster"/>
<add key="Image2FileFolder" value="D:\Binary2ImagePosters"/>
</appSettings>
</configuration>
<!--
ASP.NET
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="TESTConnectionString" connectionString="Data Source=SN78SH7;Initial Catalog=TEST;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<httpRuntime targetFramework="4.5"/>
</system.web>
<appSettings>
<add key="ImageURL" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/"/>
<add key="ImageURLW150" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w150"/>
<add key="ImageURLW300" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w300"/>
<add key="ImageURLW600" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w600"/>
<add key="ImageURLW1280" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w1280"/>
<add key="ImageURLOriginal" value="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/original"/>
<add key="ImageTMDbPosterFolder" value="D:\TMDbPoster"/>
<add key="Image2FileFolder" value="D:\Binary2ImagePosters"/>
</appSettings>
</configuration>
保存先はクライアントではなく、サーバ上のフォルダになる。サーバ上のフォルダはWeb.Config の「Image2FileFolder」で指定する。
なお、エクスポートされる画像サイズは、ListView で表示されている画像サイズに影響されない。DBに登録されているそのままのサイズでエクスポートされる。
ListViewのページを移動してExportする
90ページに移動してExportをクリック
すでに同じファイル名の画像があった場合はエラー表示する。
一括エクスポート
- ListView の表示に関係なく、テーブル内全データを一括で画像ファイルにエクスポートする。
- 「ExportAll」をクリックするとデバッグモードでも約4分で6779件の画像データを一括でエクスポートできた。
- 同名ファイルが存在していた場合は何もしない。
ソース
Binary2File.aspx
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Binary2File.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="Display" />
<asp:Button ID="ButtonExport" runat="server" Text="Export" />
<asp:Button ID="ButtonExportAll" runat="server" Text="ExportAll" />
<br />
<asp:ListView ID="ListViewPosters" 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 />
<asp:Label ID="LabelStatus" runat="server"></asp:Label>
</td>
</AlternatingItemTemplate>
<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>
<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 />
<asp:Label ID="LabelStatus" runat="server"></asp:Label>
<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>
</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>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [ID], [file_path] FROM [TMDbPoster]"></asp:SqlDataSource>
</div>
</form>
</body>
</html>
Binary2File.aspx.vb
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Partial Class ListViewPoster
Inherits System.Web.UI.Page
Private DVPosters As Data.DataView
Protected Sub ButtonExport_Click(sender As Object, e As EventArgs) Handles ButtonExport.Click
Dim Image2FileFolder As String = ConfigurationManager.AppSettings("Image2FileFolder")
For Each item In ListViewPosters.Items
Dim objID As Object = item.FindControl("IDLabel")
Dim objFileName As Object = item.FindControl("file_pathLabel")
Dim objStatus As Object = item.FindControl("LabelStatus")
If Not objID Is Nothing And Not objFileName Is Nothing And Not objStatus Is Nothing Then
Using con As New SqlConnection(SqlDataSource1.ConnectionString.ToString())
con.Open()
Dim strSQL As String = "SELECT Image FROM TMDbPoster WHERE ID = " + objID.text
Using sqlCmd As New SqlCommand(strSQL, con)
Using sdr As SqlDataReader = sqlCmd.ExecuteReader
Do While sdr.Read
Dim strFileNmae As String = Mid(objFileName.text, 2, Len(objFileName.text) - 1)
Dim strPath As String = Image2FileFolder + "\" + strFileNmae
Try
Dim fs As New FileStream(strPath, FileMode.CreateNew)
Dim bw As New BinaryWriter(fs)
bw.Write(CType(sdr.Item(0), Byte()))
objStatus.text = "Write Success"
objStatus.forecolor = Drawing.Color.Blue
bw.Close()
fs.Close()
Catch ex As IOException
objStatus.text = "Write Error" + "<br>" + ex.Message
objStatus.forecolor = Drawing.Color.Red
End Try
Loop
End Using
End Using
con.Close()
End Using
End If
Next
End Sub
Protected Sub ButtonExportAll_Click(sender As Object, e As EventArgs) Handles ButtonExportAll.Click
Dim Image2FileFolder As String = ConfigurationManager.AppSettings("Image2FileFolder")
DVPosters = SqlDataSource2.Select(DataSourceSelectArguments.Empty)
For Each row In DVPosters
Using con As New SqlConnection(SqlDataSource1.ConnectionString.ToString())
con.Open()
Dim strSQL As String = "SELECT Image FROM TMDbPoster WHERE ID = " + row(0).ToString
Using sqlCmd As New SqlCommand(strSQL, con)
Using sdr As SqlDataReader = sqlCmd.ExecuteReader
Do While sdr.Read
Dim strFileNmae As String = Mid(row(1), 2, Len(row(1)) - 1)
Dim strPath As String = Image2FileFolder + "\" + strFileNmae
Try
Dim fs As New FileStream(strPath, FileMode.CreateNew)
Dim bw As New BinaryWriter(fs)
bw.Write(CType(sdr.Item(0), Byte()))
bw.Close()
fs.Close()
Catch ex As IOException
End Try
Loop
End Using
End Using
con.Close()
End Using
Next
End Sub
End Class
概要
- ListView で表示されている分だけエクスポートする場合は、ListView で表示されている Item 分繰り返しエクスポートする。
- 一括エクスポートの場合は、テーブルから全レコードのIDとファイル名を読み込んで DataView に展開し、For Each で DataView の行数分繰り返しエクスポートする。
Visual Studio デザイン
参考
コメント
コメントを投稿