C# ile Veritabanına Resim Ekleme ve Kaydedilen Verileri Çekme

Eyl 06, 2013

Microsoft tarafından sunulan veritabanı sunucusu olan MSSQL, çok çeşitli veri tipleri üzerinde işlem yapabilmektedir. Bu veri tiplerinden biri de resim dosyalarının ikili değer (binary) olarak saklandığı image (resim) tipidir. Bu veri tipinin kullanım amacı, bazı güvenlik nedenlerinden ötürü programlarda ya da İnternet sitelerinde kullanılan resimlerin fiziksel olarak saklanamamasıdır.

.NET teknolojisinde bu yöntem sıkça kullanılmaktadır. Resimler yazılım tarafından ikili koda çevrilerek veritabanına gönderilir ve veritabanı tarafından saklanır. Ancak resimlerin boyutları büyüdükçe yazılımın çalışması yavaşlar ve veritabanı üzerinde performans kaybı yaşanır. Bu nedenle veritabanında büyük boyutlu ve çok sayıda resim saklamak önerilmemektedir.

Uygulama

Bu uygulamada ASP.NET, C# ile kullanıcıdan resim alınmış ve veritabanına ikili olarak kaydedilmiştir. Uygulama için kullanılan veritabanı tablo yapısı aşağıdaki gibidir. Fotograf isimli bu tablo üzerinde işlem yapmak için, EntityFramework teknolojisi kullanılmıştır.

Kullanıcı arayüzü ASP.NET tarafından resim adının ve resim dosyasının alınacağı girdilerden ve kullanıcıya kayıtlı resimlerin sunulacağı tekrarlayıcıdan oluşmaktadır. Bu arayüzü oluşturan kod parçası aşağıdaki gibidir:

 

<div>
     Baslik: <asp:TextBox ID="tb_YeniResimBaslik" runat="server" /><br />
     Resim: <asp:FileUpload ID="fu_YeniResimDosya" runat="server" />
     <asp:Button ID="bt_YeniResimKaydet" runat="server" Text="Yukle" 
                        onclick="bt_YeniResimKaydet_Click" />
</div>

 

<asp:EntityDataSource ID="ds_Fotograflar" runat="server"
                                  ConnectionString="name=vtEntities"
                                  DefaultContainerName="vtEntities"
                                  EnableFlattening="False" 
                                  EntitySetName="Fotograf"
                                  Select="it.[id], it.[baslik], it.[resim], it.[tarih]" />

<asp:Repeater ID="rp_Fotograflar" runat="server" 
                       DataSourceID="ds_Fotograflar"
                       OnItemCommand="rp_Fotograflar_Command">
     <HeaderTemplate>
          <table>
     </HeaderTemplate>
     <ItemTemplate>
          <tr>
               <td>
                    <img src="Resim.ashx?id=<%# Eval("id") %>"
                             alt="<%# Eval("baslik") %>" width="200px" />
               </td>
               <td>
                    <%# Eval("baslik") %><br />
                    <%# Eval("tarih") %>
               </td>
          </tr>
     </ItemTemplate>
     <FooterTemplate>
          </table>
     </FooterTemplate>
</asp:Repeater>

Yükle düğmesine tıklanıldığı anda kod tarafından resim dosyası ikili hale çevrilerek, Fotograf nesnesi oluşturlmuş ve veritabanına kaydedilmiştir. Resim dosyasını ikili hale çeviren ve veritabanına kaydeden metotlar aşağıdaki gibidir:

 

 

protected void bt_YeniResimKaydet_Click(object sender, EventArgs e)
{
     vtEntities vtBaglanti = new vtEntities();
     Fotograf yeniFotograf = new Fotograf
     {
          id = Guid.NewGuid(),
          resim = ResimToByte(fu_YeniResimDosya.PostedFile.FileName),
          baslik = tb_YeniResimBaslik.Text,
          tarih = DateTime.Now
     };

     try
     {
          vtBaglanti.AddToFotograf(yeniFotograf);
          vtBaglanti.SaveChanges();
     }
     catch (Exception)
     {
          throw new Exception("SQL Error");
     }
     finally
     {
          rp_Fotograflar.DataBind();
     }
}

private byte[] ResimToByte(string resPatika)
{
     FileInfo resBilgi = new FileInfo(resPatika);
     FileStream dosAkim = new FileStream(resPatika, FileMode.Open, FileAccess.Read);
     BinaryReader byteOkuyucu = new BinaryReader(dosAkim);

     return byteOkuyucu.ReadBytes((int)resBilgi.Length);
}

Bu işlemler ile eklenen resimler veritabanı üzerinde aşağıdaki yapıda saklanmaktadır:

 

Veritabanındaki ikili düzende kayıtlı resimler ise kullanıcıya Resim.ashx dosyası üzerinden sunulmaktadır. Bu dosya tekrarlayıcıdan, resim kimliğiyle çağırılmakta ve yazılım tarafında ilgili resmin ikili değerini alarak kendi üzerinden sunmaktadır. Metot öncelikle dosya tipini resim olarak ayarlar ve ikili kodu kendi üzerine dörder kilobaytlık parçalar halinde yazar. Bu işlemleri yapan Resim.ashx dosyası aşağıdaki gibidir:

 

public class Resim : IHttpHandler
{
     public void ProcessRequest(HttpContext context)
     {
          context.Response.ContentType = "image/jpeg";
          vtEntities vtBaglanti = new vtEntities();
          Guid fotografId = new Guid(context.Request.QueryString["id"]);
          byte[] fotografResim = (from fotograf in vtBaglanti.Fotograf
                                             where fotograf.id == fotografId
                                             select fotograf.resim).FirstOrDefault();

          Stream akim = new MemoryStream(fotografResim);
          byte[] buffer = new byte[4096];
          int byteSeq = akim.Read(buffer, 0, 4096);
          while (byteSeq > 0)
          {
               context.Response.OutputStream.Write(buffer, 0, byteSeq);
               byteSeq = akim.Read(buffer, 0, 4096);
          }
     }

     public bool IsReusable
     {
          get { return false; }
     }
}

Program çalıştırıldığında aşağıdaki gibi bir arayüz sunmaktadır: