FileUpload kontrolünün temel olarak istemciden aldığımız dosyaları sunucunun fiziksel bir konumuna kaydetmek için kullanırız. Fakat bazı durumlarda istemciden alınan bir dosyanın sunucuda güvenli şekilde saklanması için veritabanında saklama yoluna da gidebiliriz. Bu yazımda ASP.NET sunucu kontrollerinden olan FileUpload ile istemciden aldığımız bir dosyayı sunucudaki SQL Server gibi bir veritabanında nasıl saklayabileceğimizi inceleyeceğiz.
İlk olarak dosya bilgilerini saklayacağımız bir tablo oluşturuyoruz.
Tablomuzda resmin adını, binary formatta dosya içeriğini ve dosyanın MIME type bilgisini saklayacağız. FileUpload kontrolünün üç farklı özelliği bize dosyanın bu bilgilerini getirecektir. Bu özelikler ve açıklamaları aşağıdadır:
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) |
Artık sayfamızı tasarlayıp, gerekli kodlarımızı oluşturabiliriz.
<form id="form1" runat="server">
Yüklenecek dosyayı seçiniz:<br />
<asp:FileUpload ID="FileUpload1" runat="server" /> <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. Birkaç kayıt ekledikten sonra 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.
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 tarayıcıda görüntülenemez, ancak yüklenebilir dosyalardır. Aşağıdaki kod parçasında tasarladığımız bir sayfanın kullanıcı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;
}
}
}
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.
merhaba .. ben gridviewde bulunan datalar için download linki eklemek istiyorum. ancak download linkine tıkladığımda resimgoruntule.ashx handler’ını çalıstıramıorum. hata olarak "The parameterized query ‘(@id nvarchar(4000))Select * From Dosyalar Where dosyaID=@id’ expects the parameter ‘@id’, which was not supplied." bunu alıorum. yardım edebilir misiniz?
resimgoruntule handler’ını siteye eklediğimde @id bulunamadı gibi bi hata alıorum. gridview koyarak download linki ekledim. o link üzerinden handler’ı çaıstırmak istiorum. ama bir türlü dosyaID’sini handler’a aktaramadım. bu geçiş nasıl oluyor acaba ?
Büyük ihtimalle sorgunun yazımında veya sorgundaki parametre tipinde bir hata var. Bu tip hataları bana mail olarak gönderebilirsiniz, yorum olarak yazmaya gerek yok:) Mail adresim yorumun hemen altında var zaten. Sorgu ve sorguya eklediğiniz parametreleri içeren kodları ve tablodaki dosyaId kolonunun tipini mail atın, yardımcı olurum ben.
Uğur Bey öncelikle paylaştığınız kodlar için teşekkür ediyorum .Bir de soru sormak istiyorum.Benim veritabanına resim yükleyip sayfada bulunan image de göstermem lazım.Yükleme kısmını yukarıdaki gibi yaptım fakat image e veritabanından bu bilgileri alıp yükleme kısmını yapamadım.
Yardımcı olursanız çok sevinirim
Ufak bir hatırlatma:
Asp.net FileUpload kontrolü maksimum 4096KB dosya boyutunu upload edebiliyor.
Upload edilebilecek dosya boyutunu değiştirmek için web.config dosyasına
"<httpRuntime maxRequestLength="10240" />" — Maksimum 10MB
satırını eklemeliyiz.
Merhaba
Öncelikler makaleniz için teşekkürler.Güzel bir paylaşım.Bir sorum olacaktı.Bu adımlar sonrasında ekranda image yerine , direk binary degerler geliyor.Bunu nasıl ççözebilirim acaba?
Şimdiden teşekkürler,iyi çalışmalar
@Cem
Bu dediğiniz işin doğası zaten. Yani yapılan işlem sonucunda veriler veritabanında binary saklanır, doğrudan okumanız durumunda da binary gelir. Burada veriyi ancak ResimGoruntule.ashx dosyasında görüldüğü gibi sayfa output’una image olarak yazdırmak gerekir. Diğer yandan programatik olarak Image veya Bitmap tipinden bir nesneye cast edilebilir. Bunun dışındaki senaryolarda binary veri gelecektir.
hocam selam
benim connectionstring im bu >Data Source=.\\SQLEXPRESS;AttachDbFilename=D:\\WebSite1\\app_data\\db.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True
bu kendi bilgisayarımda sorunsuz çalışıyor , ancak hosta atadağım zaman çalışmıyor , veri tabanı yolunu tabiki hosta göre düzenliyorum , ancak yine çalışmıyor , ben şu baştaki .\\sqlexpress ifadesinden şüpheleniyorum
çözümü ne olabilir , yardımlarınızı bekliyorum
iyi çalışmalar
Öncelikli olarak sunucuda SQL Express driver’ları kurulumu buna bakmak lazım. Bildiğim kadarıyla çoğu hosting firması SQL Express desteği vermiyor. Sunucu sorumlularına mail atıp SQL Express destekleri olup olmadığını sorun ve eğer varsa örnek bir connection cümlesi iletmelerini rica edin. Bu şekilde daha sağlıklı olacaktır.
bu nasıl oluyor..
@kazanova Ne nasıl oluyor? Biraz daha açıklayabilir misiniz soruyu?
“The parameterized query ‘(@id nvarchar(4000))Select * From Dosyalar Where dosyaID=@id’ expects the parameter ‘@id’, which was not supplied.”
Bende de bu hatayı verdi. Kodu inceleyince şunu farkettim: id yi Request.QueryString ile alıyor ama Diğer sayfadan id’yi göndermediği için id Null geliyor.
evet bende aynı hatayı alıyorum düzeltebıldın mı pekı doruk sen ben de baya ugrastım yapamadım tıkandı kaldı proje burda
Merhaba,
Ben dll dosyalarımı sql de saklamak istiyorum. mevcut yapım dll dosyalarımın path ini sql tutuyorum ama binary tipinde saklamakta istiyorum. file stream ile sql okuyuo işlem yaptırmak istiyorum. sizce bu işlemin uygulanabilirliği nedir. saygılar.