Makale Özeti

Bu makalemizde FileUpload kontrolü ile istemciden alınan dosyaların SQL Server gibi bir veritabanında nasıl saklanacağını ve veritabanından dosyaların nasıl okunacağını inceleyeceğiz.

Makale

FileUpload kontrolü ASP.NET uygulamaların pratik şekilde istemciden alınan bir dosyanın sunucuya kaydedilmesini sağlar. Kullanımı oldukça pratik olan bu kontrolün SaveAs isimli metodu sayesinde istemciden alınan dosyayı sunucudaki fiziksel bir konuma kaydetmektedir. Bu kullanımı zaten hepimiz biliyoruzdur, ama bu yazımızda FileUpload kontrolüyle istemciden alınan bir dosyanın sunucudaki SQL Server gibi bir veritabanındaki tabloda nasıl saklanabileceğini inceleyeceğiz.

İlk olarak bir dosyayı veritabanında saklamanın sebepleri ve avantajları üzerinde konuşalım.

- Webfarm ortamlarında farklı sunucularda kurulu web uygulamamızın resim dosyalarına erişmeleri önemli bir sorundur. Resimleri tüm sunucularda senkron şekilde saklamak veya ayrı bir dosya sunucusu kullanmak mümkün olabilir. Her senaryoyu detaylı şekilde ele almak mümkün ancak burada konuyu çok uzatmamak adına daha pratik, daha stabil ve daha az maliyetli çözümün resim dosyalarını veritabanında saklamak olduğunu söylemekte bir sakınca görmüyorum.

- Bazı durumlarda belirli dosyaların sunucumuzda güvenilir şekilde saklanmasını, belirli hakları olmayanların bu dosyalara erişmemesini isteyebiliriz. Dosyaları fiziksel olarak disk üzerindeki bir klasörde saklamak ve web uygulamasının authorization(yetkilendirme) ayarlarından bu klasöre erişim kurallarını belirlesekte, dizine işletim sistemi üzerinden erişen kişiler dosyalara erişebilir. İşte bu tarz durumlarda dosyaların veritabanında saklanması tercih edilebilir. Zira veritabanında binary formatta saklanan dosyalar veritabanına erişim hakkı olmayan kullanıcılar tarafından görüntülenemez.

- Uygulama bilgilerinin saklandığı veritabanının farklı bir yere taşınması durumunda dosyalarında veritabanıyla beraber taşınır hale gelmesi önemli bir avantaj olarak düşünülebilir.

- Bahsettiğimiz avantajların dışında veritabanına bir dosya yazmanın/okumanın biraz yavaş olacağını belirtmek gerekir. Bilhassa çok büyük boyutlu dosyalarda hız sorunu yaşamak mümkündür (Resim dosyalarının istemcide cache'lenmesi bu sorunun en ideal çözümlerden biridir. Bu konuda ayrıca araştırma yapmanızı öneririm).

Öncelikli olarak istemciden alacağımız dosyayı kaydedeceğimiz tabloyu SQL Server veritabanında hazırlayalım. Aşağıdaki resimde hazırladığım tablonun kolon bilgileri görülmektedir. Bildiğiniz gibi resim, video vb. dokümanlar binary formatta oldukları için veritabanında image, varbinary gibi veri tipleri ile saklanabilmektedirler. Tablomuzda basit olarak id bilgisini, istemciden alınan dosyanın adını, dosyanın tipini(MIME type bilgisini) ve dosyanın içeriğini binary formatta saklayan 3 kolonumuz yer almaktadır.


Resim: Dosyalar tablosundaki kolonlar

Tablomuzu tasarladığımıza göre artık uygulamamızı hazırlamaya geçebiliriz. Bir web formuna eklediğimiz FileUpload ve Button kontrolü ile örneğimizi hazırlayacağız. FileUpload kontrolünden programatik olarak dosya adını, dosyanın MIME type bilgisini ve binary değerini elde etmek isteyeceğiz. Aşağıda FileUpload nesnesine ait ilgili property'leri ve açıklamalarını görebilirsiniz.

FileName: Yüklenen dosyanın adı
FileBytes: Dosyanın binary formatta içeriği (byte dizisi olarak getirilir)
PostedFile.ContentType: Dosyanın MIME type bilgisi (MIME dosyanın formatını belirleyen bir isim standartıdır)
   

Yüklenen dosyanın yukarıda görmüş olduğunuz özelliklerini veritabanına kaydedeceğiz. Aşağıda bu işlem için gerekli olan kod parçalarını görebilirsiniz.

Default.aspx

<form id="form1" runat="server">

    Yüklenecek dosyayı seçiniz:<br />

    <asp:FileUpload ID="FileUpload1" runat="server" /> &nbsp;<asp:Button

        ID="Button1" runat="server" Text="Dosyayı Yükle" onclick="Button1_Click" />

    <br />

    <br />

    <asp:Label ID="lblMesaj" runat="server" ForeColor="Red"></asp:Label>

</form>


Default.aspx.cs

public partial class _Default : System.Web.UI.Page

{

    protected void Button1_Click(object sender, EventArgs e)

    {

        if(FileUpload1.FileContent != null)

        {

            string dosyaAdi = FileUpload1.FileName; //Dosyanın adı

            byte[] dosyaIcerik = FileUpload1.FileBytes; //Dosyanın bilgilerini binary formatta getirir

            string dosyaTipi = FileUpload1.PostedFile.ContentType; //Dosyanın MIME Type bilgisini getirir

 

            SqlConnection con = new SqlConnection("data source=localhost; initial catalog=Test; integrated security=true");

            SqlCommand cmd = new SqlCommand("Insert Into Dosyalar Values(@dosya_isim, @dosya_icerik, @dosya_tip)", con);

            cmd.Parameters.AddWithValue("@dosya_isim", dosyaAdi);

            cmd.Parameters.AddWithValue("@dosya_icerik", dosyaIcerik);

            cmd.Parameters.AddWithValue("@dosya_tip", dosyaTipi);

            con.Open();

            if (cmd.ExecuteNonQuery() > 0)

                lblMesaj.Text = "Dosya başarıyla yüklendi";

            con.Close();

        }

    }

}

 

Görüldüğü gibi SQL Server'da hazırladığımız Dosyalar adındaki tablo için yazılan bir INSERT cümlesine parametre olarak eklenen dosya bilgileri bu şekilde tablomuza eklenebiliyor. Tablomuzun içeriğini Management Studio gibi bir araçtan kontrol edecek olursak aşağıdaki gibi bir görüntüyle karşılaşırız.


Resim: Tablodaki kayıtlar. Resmin içeriği binary formatta saklanır.

Resimleri başarıyla kaydettik, peki okuma işlemi nasıl gerçekleşecek? Okuma işlemi için ise tablomuzdaki kayıtları SELECT sorgusu ile okumamız gerekecek. Eğer Windows uygulamasında çalışıyor olsaydık DosyaIcerik kolonundan okunan kaydı System.Drawing.Image tipine çevirip Image gibi bir kontrolde görüntüleyebiliriz. Ancak web uygulamalarında bir resmi istemci tarafına taşımamızın yolu biraz daha farklı olacaktır. Resmin içeriği ancak istemciye yollanan cevabın(Response) içerisine yazdırılarak gönderilebilir. Dosyayı istemciye gönderirken dikkat edilmesi gereken hususlardan birisi dosyanın tarayıcıda görüntülenip görüntülenmeyeceğidir. Zira jpg, gif, xml, txt gibi dokumanlar web tarayıcısında görüntülenebilir dosyalarken, zip, exe, dll gibi dosyalar ise ancak yüklenebilir dosyalardır. Aşağıdaki kod parçasında tasarladığımız bir sayfanın kullanıya veritabanındaki bir dosyanın nasıl iletilebileceği görülmektedir.

Bu arada, dosyaya yapılan talep QueryString üzerinden resmin DosyaId kolonundaki değer ile iletilmektedir. Yine talebin daha hızlı cevaplanması için Web Form(aspx) dosyası yerine Generic Handler(ashx) dosyası kullanmak daha faydalı olacaktır.

ResimGoruntule.ashx

...

using System.Data.SqlClient;

 

public class ResimGoruntule : IHttpHandler {

 

    public void ProcessRequest (HttpContext context) {

        string id = context.Request.QueryString["id"];

        byte[] dosyaIcerik = null;

        string dosyaTipi = String.Empty;

 

        SqlConnection con = new SqlConnection("data source=localhost; initial catalog=Test; integrated security=true");

        SqlCommand cmd = new SqlCommand("Select * From Dosyalar Where DosyaId=@id", con);

        cmd.Parameters.AddWithValue("@id", id);

        con.Open();

        SqlDataReader dr = cmd.ExecuteReader();

        if (dr.Read())

        {

            dosyaIcerik = (byte[])dr["DosyaIcerik"];

            dosyaTipi = dr["DosyaTip"].ToString();

        }

        con.Close();

 

        //context.Response.AddHeader("content-disposition", "attachment; filename=" + dosyaAdi + ";"); //Download edilecek dosyanın adı belirleniyor. Bu satırın yorum durumu kaldırılırsa tüm dosyalar download işlemine zorlanacaktır.

        context.Response.ContentType = dosyaTipi; //Gönderilen dosyanın tipi belirtiliyor

        context.Response.BinaryWrite(dosyaIcerik); //Gönderilen cevabın içeriği dosyanın binary formattaki bilgileri olacaktır

    }

 

    public bool IsReusable {

        get {

            return false;

        }

    }

}


Resim: HaberId değeri 1 olan resmin tarayıcıda görüntülenmesi

Görüldüğü gibi Response nesnesinin BinaryWrite metodu byte dizisi olarak saklanan dosya içeriğini istemciye göndermektedir. Yine dosyanın tarayıcı tarafından tanınmasını ve işlemin sağlıklı şekilde tamamlanması için ContentType özelliğini de resmin MIME type değeri olarak belirliyoruz. Eğer resmin istemci tarafından download edilmesini istiyorsak kod içerisinde yorum satırı olarak bulunan ve AddHeader metodu ile sayfaya eklenen başlık bilgilerinin bulunduğu satırı normal hale getirmek gerekecektir.

Bu makalemizde FİleUpload kontrolü ile istemciden alınan bir dosyanın SQL Server gibi bir veritabanında nasıl saklanabileceğini ve saklanan dosyaların istemci tarafından nasıl görüntülenebileceğini incelemeye çalıştık. Bir başka makalede görüşmek dileğiyle.


Uğur UMUTLUOĞLU
www.umutluoglu.com
www.nedirtv.com 
twitter.com/umutluoglu