Mvc’de Çoklu Resim Yükleme ve DropBox’a Yedekleme

Selamlar;

Bugün son zamanlarda karşıma bolca çıkan toplu resim yükleme ve Upload ettiğimiz resimleri Dropbox’a nasıl yedekleyeceğimiz konusu üzerine konuşacağız. Aslında dropbox haricinde seminerlerde de bu konuya yeterince deyinmiş idim. Bir de burada en yalın hali ile konuyu ele almaya çalışacağım. Upload işlemi için Jquery ve Jquery.Form haricinde hiçbir library kullanmadan örneğimize geçelim. Tabi DrobBox için de başka bir library kullanacağız.

Öncelikle Nugetteden aşağıdaki Jquery.Form package indirilir.

jqueryF

Index.cshtml’e öncelikle aşağıdaki 2 script dosyası eklenir.

Resimleri yüklemek için aşağıda görülen “Ajax.BeginForm()” methodu kullanılır. İlk parametre “Action” ve ikinci parametre “Controller” ismidir. 3. parametre “HttpMethod” tipini yani “Post”‘u belirtmektedir. Son parametre “enctype” tarayıcıdan sunucuya form verileri gönderilirken kullanılan kodlama türünü belirtir. “AntiForgeryToken()” veriyi post ederken güvenliği sağlar. Url’e dinamik bir token ekler. Daha sonra yine server side tarafında ilgili token kontrol edilir.”<input type=’file’>” nesnesinde “multiple=’true'” özelliği çoklu dosya seçmeye yarar.

Loader

Resimlerin yüklenme sırasında yukarıda görülen “Loading” gif’inin gözükmesi için aşağıdaki kod konur. Görüldüğü gibi enbaşta gizlenmiştir.

Aşağıdaki script ile form post olduğu zaman “loader” gifinin gözükmesi ve işlem bittiği zaman tekrar gizlenmesi “ajaxForm”‘un “beforeSend” ve “complete” eventleri ile yapılmıştır.

HomeController.cs: Aşağıdaki kodlar resimler seçildikten sonra post edilen “UploadImage()”‘e aittir. “HttpPostedFileBase” türünde “IEnumerable<>” şeklinde dosya tipi beklemektedir. İlgili post edilen resimler local’de “Upload” klasörüne  kaydedilmektedir. Aynı isimde 2 resimin, kaydedilmemesi için resimin fileName’inden uzantısı çıkarılıp, yeni oluşturulan Guid() “-” işareti ile birlikte bu ismin sonuna  eklenmiş ve daha sonra uzantısı sona tekrar konarak ilgili resim kaydedilmiştir. Sonda “Thread.Sleeep” ile sistem 2sn bekletilerek yükleme logosunu ekranda daha uzun süre gözükmesi sağlanmıştı:) Ayrıca Action’ın başındaki [HttpPost] sadece post request’i ile erişilmesini sağlamıştır. Son olarak [ValidateAntiForgeryToken] ile Action’a gelen request’de “Token” kontrolü yapmakta ve böylece güvenlik büyük oranda arttırılmaktadır.

Upload

Yukarıdaki örnekde görüldüğü gibi Action “JsonResult” sonuç döndürmektedir. Şu an için “Null” değer dönülmüştür. Aşağıdaki örnekte öncelikle “MyViewModel” adında bir View Model yaratılmıştır. “Upload” klasörünün altındaki tüm dosyalar, eklenen Guid’den önceki  isim’i ilgili MyViewModel’deki “Name” özelliğine atanmıştır. Aynı zamanda MyViewModel’deki “ImageUrl” alanına ilgili dosya url’i, olduğu gibi atanmıştır. “List<MyViewModel> imageList” nesnesine herbir oluşturulan item eklenmiş ve sonunda “Upload” klasöründeki tüm dosyalar ilgili List’e eklendikten sonra result, Json(imageList) şeklinde döndürülmüştür.

HomeController.cs:

Index.cshtml(Full): Aşağıda makalenin başında yazdığımız Index.cshtml’i biraz daha geliştirdik. Görüldüğü gibi complete eventinde geriye bir Json tipinde ImageList dönülmektedir. Ilgili listenin “responseText”‘i Json’a Pars edilip, ilgili object içinde herbir item tek tek gezilerek string bir Html Table oluşturulur. Aşağıdaki kod’da dikkat edimesi gereken kısım her 3 kayıtta bir yeni satırın tablo içinde oluşturulmasıdır. İlgili tablonun içine upload edilen “<img>” nesneleri herbir kolonun yani “<td>” elementi içine konur. Daha sonra oluşturulan Html text, form içindeki “imageList” div’in html’ine basılır.

Şimdi sıra geldi yüklenecek resimleri DropBox’a yedeklemeye:

Bunun için öncelikle https://www.dropbox.com/developers adresine gidilir.

1-)Buradan aşağıdaki gibi sol taraftaki “App Console” seçilir.

Drop1

2-)Sağdaki drop2 button’una basılır.

3-) Aşağıda görüldüğü gibi öncelikle “Dropbox API app” seçilir. Daha sonra dropbox’daki tüm klasörlere erişmek için “My app needs access to files already on Dropbox” seçilir. Son olarak tüm dosya tiplerine erişmek için “All files types” seçilir. Ve yaratılacak application’a bir isim verilip “Creat app” buttonuna basılır.

Drop3

4-)Uygulama yaratıldığında aşağıdaki gibi bir ekran ile karşılaşılır. “App  key” ve “App secret”. Bizim için uygulamada kullanılacak önemli parametrelerdir. Ayrıca ilgili izin verildikten sonra dönüş yapılacak Url yani “Redirect URIs” aşağıdaki gibi “https://localhost:44300/” olarak belirtilmiştir.

drop4

Şimdi sıra geldi projemize bu yeni yarattığımız “UploadImages” uygulamamızı implemente etmeye.

1-) Bunun için aşağıda görüldüğü gibi “Spring.Social.Dropbox”  paketi Nuget’den indirilir.

drop5

2-) DropBox ekranında hatırlarsanız “RedirectURIs” “https” ile başlıyordu. Bunun için proje tıklanıp, property ekranından SSL Enabled’a True değeri aşağıdaki gibi atanır.

drop6

3-) Daha sonra aşağıda görülen SSL URL kopyalanır ve Proje sağ tıklanıp Properties seçilir. Solda Web sekmesi seçildikten sonra Project Url kısmına kopyalanan bu SSL adresi yapıştırılır ve kaydedilir.

Web

4-) Namespace’a aşağıdaki kütüpahaneler eklenir.

HomeController.cs:

5-) HomeController.cs’e aşağıdaki “LoginDrop()” methodu eklenir. Öncelikle “DrobboxServiceProvider”‘a DropBox sayfasından aldığımız “App key” ve “App secret” parametre olarak atanır. Ayrıca bir de Full erişim yetkisi olarak “AccessLevel.Full” verilir. Daha sonra yaratılan nesne session’a atılır. Ayrıca “Token” almak için request’de kullanacağımız “IOAuth1Operations” yaratılır ve session’a atılır. “OAuthToken”‘da yaratılan “oauthOperations”‘ın “FetchRequestTokenAsync()” methodu ile asenkron olarak çekilir. Daha sonra ilgili app’in bu projede kullanılabilmesi için izin alınacak “DropBox” sayfasının url’i parametre olarak”CallbackUrl” dediğimiz geri dönülecek sayfanın url’i ve bu sayfanın lokasyonu parametre olarak belirlenir. Ve daha sonra  “oauthOperations.BuildAuthorizeUrl()” methodu ile ilgili url çekilir. Tabi ilgili izinin DropBox’dan alınabilmesi için çekilen bu url’e “Redirect” ile yönlenilir.

6-) Aşağıda Dropbox’dan web sayfasının yaratılan “UploadImages” application’ını kullanması için izin istendiği ekran görünüyor. “Allow” button’una basılarak ilgili izin verilmiş olunur.

drop7

7-) İzin verildikten sonra “https://localhost:44300” yani HomeController/Index.cshtml sayfasına geri dönülür. Böylece Dropbox’a bağlanılmış olunur.

8-) Aşağıda UploadImage() methodu asenkron olarak değiştirilmiştir. İlgili resimler yüklendikten sonra dropbox’a da atılması için bir “IDropbox” nesnesine ihtiyaç vardır. Öncelikle DropBox RedirectUrl’den dönen”accessToken”, “IOAuth1Operations.ExchangeForAccessTokenAsync()” methodu ile asenkron olarak çekilir. Daha sonra session’daki “DropboxServiceProvider.GetApi()” methoduna az önce çekilen “accessToken”‘ın “Value” ve “Secret”‘ değerleri parametre olarak geçilerek, “IDropbox” nesnesi oluşturulur. Artık bu nesne ile Dropbox için birçok işlemi gerçekleştirebiliriz. Bu nesneyi session’a almamızın nedeni ise session süresi boyunca tekrardan Dropbox sayfasından izin alınmasını engellemektir.

9-) Örneğin “dropboxApi” nesnesi ile yapılabilecek işlerden biri Dropbox’da belirlenen bir klasördeki dosyalar “Task<Entry>” türünde “dropboxApi.GetMetadataAsync(“UploadImages”)” ile asenkron olarak alınabilmesidir. Aşağıda “UploadImages” altındaki resimlerin path’leri “Debug=>Windows=>Output” altına yazdırılmıştır.

drop8

Yine istenir ise Kullanıcı bilgileri “dropboxApi” ile aşağıdaki gibi çekilebilir.

me

10-) Tüm atılacak dosyalar tek tek gezilerek ilgili proje altındaki Upload klasörüne kaydedilir. Aynı zamanda ilgili resim, Dropbox altında “UploadImages” klasörüne “dropboxApi.UploadFileAsync()” methodu ile asenkron olarak yüklenerek aşağıdaki gibi yedeklenir.

HomeController.cs(Full):

Yukarıdaki örnekde proje içindeki bir folder’a çoklu olarak seçtiğimiz resimleri Ajax.Post ile upload ederken aynı zamanda Dropbox’da yedekledik. İş hayatında böyle bir seneryo ile karşılaşmanız pek de mümkün değildir. Bu makalede amaç Mvc ile toplu resim yüklemeyi ve Dropbox ile etkileşimi göstermektir. Aslında yapılması gereken, seçilen tüm resimleri ya bir Image Cdn’e ya da cloude’a örneğin Azure Blob Stroge’a konmasıdır. Eğer local folder’dan 1 milyon resim için request çekilse idi sistemin patlamaması işten bile değildi. Bunun çözümü için çekilen resimlerin cache’e alınması ve istendiğinde buradan verilmesi daha doğrudur. Ayrıca resimlerin, code ile oluşturulan bir html string olarak basılması yerine, javascript framworklerinden AngularJS  veya KnockoutJS gibi kütüpahanelerin kullanılıp ilgili view modelin doldurulması ve bu modeli kullanan elementlerin, yüklenen resimleri göstermesi tercih edilmelidir. Bir başka çözüm de bunun bir Mvc projesi olmasından dolayı UploadImage() methodunun dönüş tipinin partial view olarak belirlenmesidir.

Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hoşçakalın.

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

7 Cevaplar

  1. Romario dedi ki:

    Makaleye ilk baktığımda .NET’te Dropbox API’sini kullanan paket mi vardı diye düşündüm ilk başta fakat kodları inceleyince Java Spring’in social.dropbox paketinin kullandığını gördüm yani Java Spring framework’u .NET ‘e portlamışlar. Spring ‘in .NET’de kullanım örneği vermesi açısından gayet iyi bir makale.

  2. Kadir dedi ki:

    Merhaba, Tüm adımları uyguladım. Fakat izin için gerekli işlem yapılamıyor. Dolayısyla dropbox’a ulaşamıyor. Sebebi ne olabilir?

    • borsoft dedi ki:

      Selamlar,
      Sayfanızın https olması gerekiyor.(SSL verildiğine emin olun) Erişilecek klasörün ayrıca dropbox’dan yetkilendirilmesi gerekiyor. Ayrıca dropbox’a erişecek sayfa url’inin portu ile düzgün
      varilmiş olması gerekmektedir.

      İyi çalışmalar.

  3. Arda dedi ki:

    Hocam yazınız çok güzel teşekkürler emeğinize sağlık. Ben bir uygulama üzerinde resim yükleme işlemi yaptığım sırada eğer internet hızınız yavaş ise uygulama token hatası veriyor ve resim yüklenmiyor. Web config ayarlarından boyut ve süre ayarlaması yaptım ama bir sonuç alamadım. Ne yapabilirim acaba?

    • borsoft dedi ki:

      Selamlar Arda,

      Makale yazılalı yaklaşık 1 yıl olmuş. O zaman böyle bir hata hiç almadım. Bu tarz third party firmalar kodlarını çok hızlı ve geriye dönük destek vermeden değiştirebiliyorlar. Bir de aynı işlemi başka bir networkden deneyebilirmisin? Belkide internete girdiğin ağa üzerinde veya makinada bir güvenlik duvarına takılıyorsundur.

      İyi çalışmalar.

      • Arda dedi ki:

        Hocam sistemi uzun uzun inceledim ve request süresi uzun olduğu zaman request timeout oluyor. Web.config üzerinde ayarlamalar yaptım ama bir sonuç alamadım.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir