Makale Özeti

Herhangi bir Silverlight 2.0 uygulamasında kullanılan tüm materyalleri sunucu tarafından bir ZIP dosyası olarak alıp istemci tarafında ZIP dosyasındaki kaynakları kullanabilirsiniz. Makalemizde bu işlemleri Silverlight 2.0 ile beraber .NET kullanarak nasıl yapabileceğimize değiniyoruz.

Makale

Silverlight 1.0 içerisinde sunucu tarafından ZIP dosyaları alarak bunların içerisindeki dosyaları istemci tarafında çıkartarak kullanabiliyor olmak büyük avantaj sağlıyordu. Özellikle böyle bir işlevsellik sağlamak için de neredeyse hiçbir ek kod yazmıyor olmamız şaşırtıcı bir kolaylıktı. Bu şaşkınlığımızı almak adına Silverlight 2.0 Beta 1 içerisinde işler biraz daha zorlaştırılmış durumda. Gelin bir örnek ile ilerleyelim. Sayfamızda iki adet resim göstermek istiyoruz. Bu resimler bir ZIP dosyası içerisinde sunucuda yer alacak.

<UserControl

  xmlns="http://schemas.microsoft.com/client/2007"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  x:Class="SilverlightApplication6.Page"

  Width="640" Height="480">

 

  <Grid x:Name="LayoutRoot" Background="White" >

    <Image HorizontalAlignment="Left" Margin="42,64,0,235" Width="221" x:Name="Resim1" />

    <Image Margin="303,64,118,235" x:Name="Resim2"/>

    <Button Height="53" HorizontalAlignment="Stretch" Margin="200,0,301,138" VerticalAlignment="Bottom" Content="Button" x:Name="Dugme"/>

  </Grid>

</UserControl>

Yukarıdaki örnek Silverlight 2.0 Beta 1 projemize ait Page.xaml dosyasının kodunu inceleyebilirsiniz. Hedefimiz düğmeye tıklandığında sunucudaki fotolar.zip dosyasını istemciye indirerek içerisindeki iki farklı resmi ekrandaki iki boş Image tagının içerisine yerleştirmek. İlk olark sunucudan asenkron bir istek ile veri alabilmek için bir WebClient nesnesi yaratmamız gerekiyor.

Private Sub Dugme_MouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles Dugme.MouseLeftButtonDown

    Dim Talep As New System.Net.WebClient

    AddHandler Talep.OpenReadCompleted, AddressOf VeriGeldi

    Talep.OpenReadAsync(New Uri("fotolar.zip", UriKind.Relative))

End Sub

Yukarıdaki kodumuz Silverlight uygulamamızda düğmeye basıldığında çalışacak olan kodun ta kendisi. İlk olarak Talep adında bir WebClient nesnesi yaratıyoruz. Sonrasında bu WebClient'ın OpenReadCompleted durumunda çalışacak olan VeriGeldi fonksiyonuna ait atamayı tamamlıyoruz. Böylece sunucudan istediğimiz veri istemciye ulaştığında birazdan yazacağımız VeriGeldi fonksiyonu / event handler'ı çalışacak.

Son satırda OpenReadAsync metodu ile sunucudan fotolar.zip dosyasını istiyoruz. Söz konusu isteği gerçekleştirirken OpenReadAsync metoduna bir Uri vermemiz gerekiyor bunun için Relative bir Uri yaratıyoruz. Relative yaratmamızın nedeni fotolar.zip dosyasının Silverlight uygulamasının çalıştığı adres ile aynı konumda bulunacak olması.

    Dim GelenVeri As System.IO.Stream = e.Result

    Dim FotoStream As System.IO.Stream = Application.GetResourceStream(New System.Windows.Resources.StreamResourceInfo(GelenVeri, Nothing), New Uri("creek.jpg", UriKind.Relative)).Stream

Artık yavaş yavaş VeriGeldi event-handlerımızda çalışacak kodları yazmaya başlayalım. İlk satırda söz konusu event-handlerımıza parametre olarak gelecek olan System.Net.OpenReadCompletedEventArgs tipinde e değişkeni üzerinden e.Result diyerek sunucudan gelen Stream'i alıyoruz. Sonraki satırda işler biraz karışık. Elimizdeki Stream'i, yani GelenVeri değişkenini bir StreamResourceInfo'ya dönüştürmemiz gerekiyor. Bunu da Application.GetResourceStream metoduna birinci parametre olarak veriyoruz. Böylece GetResourceStream metodu artık nereden Resource çıkartacağını biliyor. ZIP dosyamızın gelen stream'ini dönüştürerek GetResourceStream'e verdikten sonra tanımlamamız gereken ikinci parametre ise ZIP dosyası içerisinden hangi dosyayı yani Resource'u almak istediğimiz. Bunun için de bir Relative Uri yaratarak GetResourceStream'a metoduna ikinci parametre olarak veriyoruz. Artık GetResourceStream gerekli veriyi kendisine verdiğimiz ZIP Stream içerisinden alarak bize yine bir Stream olarak verecektir. FotoStream değişkenimizi de bu şekilde yakaladıktan sonra artık işlemlere devam edebiliriz.

    Dim Foto As New System.Windows.Media.Imaging.BitmapImage

    Foto.SetSource(FotoStream)

    Resim1.Source = Foto

    Resim1.Measure(New System.Windows.Size)

FotoStream'imizden bir Foto yaratabilmek için Foto adında bir BitmapImage nesnesi yaratıyoruz. Söz konusu nesnenin SetSource metodunu kullanarak doğrudan elimizdeki FotoStream'i kendisine aktarıyoruz. Artık elimizde bir Foto bulunduğuna göre bunu XAML kodumuzdaki Resim1'in Source özelliğine aktarabiliriz. Son olarak Resim1'e ait Measure metodunu da çağırarak görsel anlamda Resim1'in ekranda kaplayacağı yer olarak kendisini toparlamasını sağlamamız gerekiyor. Aksi halde resim yüklense de daha önce Resim1'in içi boş olduğu ve boyutu ekranda ufak olduğu için gözükmeyecektir. Artık tek yapmamız gereken aynı işlemleri ikinci resim için de yaparak GelenVeri'den ikinci dosyamızı da almak ve Resim2 içerisine yerleştirmek.

Private Sub VeriGeldi(ByVal sender As Object, ByVal e As System.Net.OpenReadCompletedEventArgs)

    Dim GelenVeri As System.IO.Stream = e.Result

    Dim FotoStream As System.IO.Stream = Application.GetResourceStream(New System.Windows.Resources.StreamResourceInfo(GelenVeri, Nothing), New Uri("creek.jpg", UriKind.Relative)).Stream

    Dim Foto As New System.Windows.Media.Imaging.BitmapImage

    Foto.SetSource(FotoStream)

    Resim1.Source = Foto

    Resim1.Measure(New System.Windows.Size)

    Foto = New System.Windows.Media.Imaging.BitmapImage

    Foto.SetSource(Application.GetResourceStream(New System.Windows.Resources.StreamResourceInfo(GelenVeri, Nothing), New Uri("autumn leaves.jpg", UriKind.Relative)).Stream)

    Resim2.Source = Foto

    Resim2.Measure(New System.Windows.Size)

End Sub

Peki bu ZIP dosyası içerisinde sadece resimler mi bulunabilir? Tabi ki hayır. Aynı ZIP dosyası içerisinde bir de deneme.txt adında metin dosyası bulunduğunu varsayalım ve söz konusu dosya içerisinden ufak bir metni alıp düğmemizin üzerine yazdıralım.

    Dim MetinStream As System.IO.Stream = Application.GetResourceStream(New System.Windows.Resources.StreamResourceInfo(GelenVeri, Nothing), New Uri("deneme.txt", UriKind.Relative)).Stream

 

    Dim bitler(MetinStream.Length) As Byte

    MetinStream.Read(bitler, 0, MetinStream.Length)

    Dim Metin As New System.Text.StringBuilder

    For Each bit As Byte In bitler

        Metin.Append(Convert.ToChar(bit))

    Next

    Dugme.Content = Metin.ToString

Her zamanki gibi yeni bir Stream yaratarak elimizdeki GelenVeri üzerinden ZIP dosyasında deneme.txt'yi alıyoruz. Stream'imizi bir byte dizisine aktardıktan sonra her bir byte'ı tek tek karaktere çevirerek bir StringBuilder yardımı ile sürekli bir metne dönüştürüyoruz. Son olarak elimizdeki metni de düğmemizin üzerine yazdırıyoruz.

Böylece harici bir ZIP dosyasını istemci tarafında asenkron olarak indirmiş ve sonrasında da dosya içerisindeki iki farklı resmi farklı Image nesnelerine aktarmış olduk. Bu kadarla kalmayıp aynı ZIP dosyası içerisindeki bir TXT dosyasından da metin alarak kullandık. Sonuç olarak istemci tarafından sunucuya sadece bir istek yolladık ve tek bir dosya aldık. Ayrıca aldığımız dosyanın sıkıştırılmış olduğunu da unutmamakta fayda var.

Hepinize kolay gelsin.

Daron Yöndem
MVP, MCT, MCPD, MCITP, MCTS
MCSD, MCAD, MCDBA, MCP, ACP, ICSD
http://daron.yondem.com

*Bu makale Silverlight 2.0 Beta 1 kullanılarak yazılmıştır.