Blob Ortamında File System Etkisi yaratmak

0 dakikada yazıldı

29762 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 ;)