SL 2.0'da ZIP içerisinden asenkron kaynak kullanımı.

0 dakikada yazıldı

5788 defa okundu

Düzenle

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.