Blob Ortamında File System Etkisi yaratmak

0 dakikada yazıldı

30002 defa okundu

Düzenle

[Aşağıdaki makalenin SDK2.5 ile beraber yeni Azure özelliklerine uygun
şekilde güncellenmiş halini
burada
bulabilirsiniz.]

Blob konusunu inceledikçe aslında adam akıllı dosya tutabileceğimiz :)
süper bir yer olduğu hissiyatı eminim ki sizin de içinizi kaplamıştır.
Bu düşünce yapısı ile ilerlerken aslında akla gelebilecek daha bir sürü
soru var. Örneğin bir sitede kullandığımız CSS, JavaScript dosyaları
acaba sitenin bir parçası mı olmalı yoksa Blob'da mı durmalı :)

Nereden çıktı bu da şimdi diyebilirsiniz ama bir düşünün. En ufak CSS
değişikliğinde tüm service package'ı tekrar yaratıp upgrade süreci
başlatmak ister misiniz? Aynı soru belki sitenizde kullandığınız ve site
tasarımının bir parçası olan görsel dosyaları için de geçerli. Sitedeki
şirket logosu bir blobda dursa daha iyi olmaz mı?

Tüm bu soruları kendi kendimize sora duralım ister bu gibi ihtiyaçlar
yüzünden olsun ister eski alışkanlıkar sonuç itibari ile Blog
Storage'daki tek klasörlere yapısı olarak gözüken Container'lar bize
yetmeyecek galiba :) Container'ları iç içe koyamayacağımızdan
bahsetmiştim değil mi? Bu konuya canınız sıkılıyorsa işte süper olmasa
da işin çözümü şöyle...

File System Etkisi

Bir sunucudaki klasörlerin web ortamına yansıma şekli malum URL'de
kendini gösterir. Her ne kadar artıkl URLReWriting sayesinde
delikanlılığın kitabı tekrar yazılsa da :) sonuç itibari URL'deki
ayrımlar çoğu zaman bizim için mantıksal ayrımlar şeklinde dosyaların
yönetimi için ciddi yardımcı bir öğedir. Aynı etkiyi Azure'da Blob
Storage'da yakalayabilir miyiz? sorusuna "Evet" cevabını verebilirim :)
ama birazdan her ne yaparsak yapalım sakın unutmayın :) aslında böyle
birşey yok :) yapacağımız herşey sanal, hala bloblarınız bir container
içerisinde olacak.

[C#]

CloudStorageAccount account = 
        CloudStorageAccount.FromConfigurationSetting("blobConnection");
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("dosyalar");
container.CreateIfNotExist();

BlobContainerPermissions containerPermissions = new BlobContainerPermissions();
containerPermissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(containerPermissions);
            
var blob = container.GetBlobReference("resimler/" + FileUpload1.FileName);
blob.UploadFromStream(FileUpload1.FileContent);

Response.Write(blob.Uri.ToString());

Çakallığın farkına vardınız mı? :) Blob ismimiz artık sadece dosya ismi
değil. Yukarıdaki kod bloba isim olarak "resimler/" ile beraber dosya
adını veriyor böylece blobun ismi "resimler/ornek.jpg" gibi birşey
oluyor. Peki bunun URL'e yansıması nasıl olacak?

Blob adını istediğimiz gibi verince URL de istediğimiz gibi oldu :)
Blob adını istediğimiz gibi verince URL de istediğimiz gibi oldu :)

Nasıl? Güzel oldu mu :) Şimdi tabi ki diyeceksiniz ki... "tamam güzel de
bu dosyaların yönetimini kolaylaştırmıyor" ve kesinlikle haklısınız :)
Bu noktaya kadar sadece web sitemize girip bu adresi gören ziyaretçileri
kandırmış olduk. Yoksa arka planda değişen hiçbirşey olmadı, olamaz da.
Ammmaaa! :)

StorageClient diye bir wrapper kullanıyoruz ya :) İşte onun içindeki
bazı ek ilginç hareketler Container'lar içerisinde sanal klasörler
varmış gibi listelemeler yapabilmemizi sağlıyor. Böylece normal bir
dosya sisteminden beklediğimiz gibi klasörleme mantığını kodda da
kullanabiliyoruz.

[C#]

CloudStorageAccount account = 
        CloudStorageAccount.FromConfigurationSetting("blobConnection");
CloudBlobClient blobClient = account.CreateCloudBlobClient();

CloudBlobDirectory directory = blobClient.GetBlobDirectoryReference("dosyalar");
foreach (var blobItem in directory.ListBlobs())
{
    Response.Write(blobItem.Uri + "<br/>");
} 

Yukarıdaki kodda ilginç birşey var farkındaysanız. Container konusunda
hiç bilgi yok. Bu noktada container'a da sanal bir klasör muamelesi
yapmış oluyoruz. "dosyalar" container adımızken onu bir klasörmüş gibi
CloudBlobDirectory olarak alıp içindeki blobları listelemesini
istiyoruz.

Sanal klasörde neler var?
Sanal klasörde neler var?

Gördüğünüz üzere blob listesi istememize rağmen sadece bir klasör adı
geldi :) Aslında blob listesi istedik ve bize CloudBlobDirectory geldi.
Buradan yola çıkarak bir adım daha içeriye girip resimler sanal
klasöründeki blobları almak istersek aşağıdaki şekilde ilerleyebiliriz.

[C#]

CloudStorageAccount account = 
    CloudStorageAccount.FromConfigurationSetting("blobConnection");
CloudBlobClient blobClient = account.CreateCloudBlobClient();

CloudBlobDirectory directory = blobClient.GetBlobDirectoryReference("dosyalar");

foreach (var blobItem in directory.ListBlobs())
{
    if (blobItem is CloudBlobDirectory)
    {
        foreach (var blobItemNested in ((CloudBlobDirectory)blobItem).ListBlobs())
        {
            Response.Write("Dosya:" + blobItemNested.Uri + "<br/>");
        }
    }
    Response.Write("Sanal Klasör:" + blobItem.Uri + "<br/>");
} 

Kodun foreach ile başlayan noktasından itibaren manzaraya bakacak
olursan aslında container adımız olan dosyalar'ı bir klasör olarak
kabul edip içindeki blobları dönüyorum. Bu dönüş sürecinde :) gelen
nesnenin bir CloudBlobDirectory olup olmadığını kontrol edip (yani
klasör olup olmadığını bir anlamda anlayıp) eğer klasörse tekrar onun
altından da bir ListBlobs çekerek dosyaları alabiliyoruz.

Klasör ve dosya ayrımında güzel bir adım attık gibi.
Klasör ve dosya ayrımında güzel bir adım attık gibi.

Kodumuzun sonucunu da yukarıda incelerseniz tam da istediğimiz gibi bir
noktaya geldik sanırım. Geriye birkaç nokta daha kaldı belki de :)
Bunlardan ilki klasör yaratbilme. Maalesef bu konuda bire bir
System.IO'ya benzetilebilecek bir yapı yok. Unutmayın sonuçta sanal
klasör dediğimiz şeyler aslında blobların isimleri :) Sanal klasör ve
dosya ayrımını yapan StorageClient wrapper. Yani aslında şu an ne
yapıyorsak bunlar sorgular şeklinde Container seviyesinde
çalıştırılıyorlar.

[C#]

CloudStorageAccount account = 
        CloudStorageAccount.FromConfigurationSetting("blobConnection");
CloudBlobClient blobClient = account.CreateCloudBlobClient();

foreach (var blobItem in blobClient.ListBlobsWithPrefix("dosyalar/resimler/"))
{
    Response.Write(blobItem.Uri + "<br/>");
}

Ayrıca eğer isterseniz belirli bir path bilgisi vererek de yukarıdaki
gibi bir sorgu çalıştırabilirsiniz. Tabi "path" diyoruz ama :) aslında o
isimle başlayan blobları aramış oluyoruz. Özellikle yukarıdaki koda
baktığımızda bir sıkıntı daha var ki o aslında çok kritik. Container
üzerinden arama yapılmadığı için aslında cross-container bir sorgu
göndermiş oluyoruz ki bu da blobclient üzerinden tüm blob içeriğini
aramak anlamına geliyor. Aman dikkat!

[C#]

CloudStorageAccount account = 
        CloudStorageAccount.FromConfigurationSetting("blobConnection");
CloudBlobClient blobClient = account.CreateCloudBlobClient();

BlobRequestOptions options = new BlobRequestOptions();
options.UseFlatBlobListing = true;

CloudBlobDirectory directory = blobClient.GetBlobDirectoryReference("dosyalar");
foreach (var blobItem in directory.ListBlobs(options))
{
    Response.Write(blobItem.Uri + "<br/>");
} 

Son olarak eğer ki klasör falan benim umrumda değil :) Bana herşeyin
listesini getir direk, Container altındaki herşeyi istiyorum derseniz
yukarıdaki şekilde UseFlatBlobListing değerini True verirseniz
herşeyin listesini alabilirsiniz.

Kolay gelsin ;)