SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする

目的

SQLServerのテーブル TMDbPosters に映画のポスター画像をバイナリ(VARBINARY)で保存している。これを指定するフォルダに画像ファイルとしてエクスポートする。

ポスター画像がバイナリで登録されているテーブル「TMDbPosters」
画像バイナリ格納テーブル

  • 列「ImageはVARBINARY(MAX)でポスター画像を格納している。
  • 列「file_Path」はバイナリ登録前のポスター画像のファイル名。

 

完成イメージ

ポスター画像をListView で表示するのは SQL Server に FILESTREAM で登録されている画像を ASP.NET のListView で並べて表示する を参照。これをベースに作成した。

SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする
W:ポスターの横幅
H:ポスターの高さ
ボタン「Display」:W、Hで指定したサイズでポスターを再描画する
ボタン「Export」:表示されている画像を画像ファイルとしてエクスポートする
ボタン「ExportAll」:テーブルに格納されている全画像を画像ファイルとしてエクスポートする

 

動作

「Export」をクリックすると、ListView に表示されているポスターが、Web.Config で指定したフォルダにエクスポートされる。
SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートするSQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする0

保存先

保存先2保存先3

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>

保存先はクライアントではなく、サーバ上のフォルダになる。サーバ上のフォルダはWeb.Config の「Image2FileFolder」で指定する。

なお、エクスポートされる画像サイズは、ListView で表示されている画像サイズに影響されない。DBに登録されているそのままのサイズでエクスポートされる。
SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする

 

ListViewのページを移動してExportする

90ページに移動してExportをクリック

SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートするSQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする3

保存先4

すでに同じファイル名の画像があった場合はエラー表示する。

SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする4

 

一括エクスポート

  • ListView の表示に関係なく、テーブル内全データを一括で画像ファイルにエクスポートする。
  • 「ExportAll」をクリックするとデバッグモードでも約4分で6779件の画像データを一括でエクスポートできた。
  • 同名ファイルが存在していた場合は何もしない。


SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする 一括エクスポート

保存先5保存先6

ソース

 

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 デザイン

SQLServerにバイナリで保存されている画像をASP.NETで画像ファイルとしてエクスポートする7

 

参考

DB画像Image型→ローカル保存について - 楽天 みんなで解決!Q&A

例外のトラブルシューティング : System.IO.IOException

コメント

このブログの人気の投稿

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

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

IKEAの鏡を壁に取り付ける