Enes TAŞ

Developer

C# İle Google Drive API Kullanımı 10.09.2020

Bu makalede C#.Net ortamında Google Drive API kullanımını örnek bir uygulama üzerinden ele alacağız. Makale için drive üzerinde hemen hemen tüm işlemlerin yapılabildiği örnek bir winform uygulaması hazırladım, makalede bu uygulamadan görüntüler de paylaşacağım ve makale sonunda örnek uygulamayı da paylaşacağım. 

Uygulamada Google Drive'a klasör oluşturma, dosya yükleme, sürükle bırak ile dosya yükleme, dosya silme, dosyayı yeniden adlandırma, dosya kopyalama ve taşıma, dosya indirme, dosya arama gibi işlemleri yapabileceğiz. Makalede ise uygulama üzerinden dosya listeleme, klasör oluşturma, dosya yükleme, dosya silme gibi örnekleri ve kod parçalarını vereceğim. Tüm kodlara paylaştığım uygulama üzerinden erişebilir, kendi ayarlarınızı yaptıktan sonra canlı haliyle de inceleyebilirsiniz. Hatta bence kullanışlı da bir uygulama olduğunu düşündüğüm için kullanabilirsiniz de :)

Uygulama içerisinde tüm kodların yorumlaması da mevcut, o nedenle her ayrıntıyı burada anlatmaya çalışarak makalenin uzamasını ve sizlerin vaktini çok almak istemiyorum. Uygulamamızın görüntüsü aşağıdaki gibidir. 

 


Google Drive API kullanabilmek için öncelikle Google Developer Console üzerinden bir proje oluşturmamız gerekiyor. Buraya tıklayarak Developer Console hesabınızdan bir proje oluşturabilirsiniz. 



Projemizi oluşturduktan sonra projemize bir kimlik bilgisi eklememiz gerekiyor. Önce hangi kimlik bilgilerine ihtiyacımız olduğunu aşağıdaki sihirbaz yardımıyla anlayabiliriz.

 


Bu adımı da geçtikten sonra OAuth izin ayarlamaları için karşımıza bir pop-up çıkıyor. İzin Ekranını Ayarla seçeneğine tıklayarak devam ediyoruz, bu işleme tıklayınca yeni sekmede bir ekran açılıyor. Çıkan ekranda kullanım türünü seçtikten sonra bir uygulama ismi girerek kaydet diyoruz. 


Sonrasında bir önceki sekmeye geri dönerek Yenile butonuna tıklayıp, istemci kimliğimizi oluşturuyoruz. İstemci kimliğimiz tanımladıktan sonra oluşan client_id.json dosyasını indiriyoruz. Bu dosyayı API Authorization işleminde kullanacağız, makale sonunda paylaşacağım uygulamada programın çalıştığı dizine atmanız yeterli olacaktır. 


Google Developer Console üzerinden gerekli tüm işlemleri yaptıysak kodlama kısmına geçebiliriz. Öncelikle projemize Google.API kütüphanelerini eklememiz gerekiyor. Bunun için Nuget Package'ı kullanıyoruz.  Google.Apis.Drive olarak aratıp, Google.Apis.Drive.v3 paketini install ediyoruz. 


Dosyamızı da uygulamanın çalışacağı dizine (bin/Debug) attıysak, authorization işlemini aşağıdaki kod ile sağlayabiliriz. 

private DriveService service;

private readonly string[] Scopes = new string[] { DriveService.Scope.Drive, DriveService.Scope.DriveFile, DriveService.Scope.DriveReadonly };

/// <summary>
/// Authorization işlemi yapılır, 
/// öncesinde google dev. console üzerinden proje açılıp 
/// api kullanımı için gerekli işlemler yapılmalı ve client_id.json dosyası alınmalı
/// client_id.json dosyası programın çalışacağı dizine atılmalı
/// </summary>
public void Authorize() {
    UserCredential credential;

    if (!System.IO.File.Exists(Application.StartupPath + "/client_id.json")) {
        throw new Exception("client_id.json dosyası bulunamadı");
    }

    using (var stream = new FileStream(Application.StartupPath + "/client_id.json", FileMode.Open, FileAccess.Read)) {
        credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.Load(stream).Secrets,
            Scopes,
            Environment.UserName,
            CancellationToken.None,
            new FileDataStore(Application.StartupPath + "/google-tokens", true)
        ).Result;
    }

    service = new DriveService(new BaseClientService.Initializer() {
        HttpClientInitializer = credential,
        ApplicationName = "GoogleDriveExample",

    });

    service.HttpClient.Timeout = TimeSpan.FromMinutes(100);
}


Authorization işlemi sırasında uygulama google hesabımızdan izin isteyecek, izin ekranından onay verdikten sonra API'yı kullanmaya başlayabiliriz. 

Drive'dan dosya listeleme ve arama işlemleri ile başlayalım. Bunun için aşağıdaki gibi bir method hazırladım. 

/// <summary>
/// drive'dan dosya çekme
/// </summary>
/// <param name="query">query varsa kullanır, yoksa klasörler hariç her dosyayı getirir</param>
/// <returns></returns>
public List<Google.Apis.Drive.v3.Data.File> GetFiles(string query = null) {
    List<Google.Apis.Drive.v3.Data.File> fileList = new List<Google.Apis.Drive.v3.Data.File>();
    FilesResource.ListRequest request = service.Files.List();
    request.Q = query ?? "mimeType != \"application/vnd.google-apps.folder\"";

    // hangi alanların gelmesini istiyorsak burada belirtiyoruz
    request.Fields = "nextPageToken, files(id, name, createdTime, modifiedTime, mimeType, description, size)";

    //dosyalar parça parça geliyor, her parçada nextPageToken dönüyor, nextPageToken null gelene kadar bu döngü devam eder.
    // null dönerse tüm dosyalar çekilmiştir
    do {
        try {
            FileList files = request.Execute();

            // her partta gelen dosyaları fileList listesine ekliyoruz
            fileList.AddRange(files.Files);
            request.PageToken = files.NextPageToken;
        }
        catch (Exception e) {
            Console.WriteLine("An error occurred: " + e.Message);
            request.PageToken = null;
        }
    } while (!string.IsNullOrEmpty(request.PageToken));

    return fileList;
}

Method query parametresi alıyor, eğer parametre gönderilmezse varsayılan olarak klasör olmayan tüm dosyaları getirmesini istedim.


Uygulamada ise önce Root altındaki klasör ve dosyaları getirmesini, sonra o klasörler içerisinde gezebilmeyi sağladım. Root altındaki dosya ve klasörleri getirebilmesi için bir query oluşturuyoruz.

Sadece root için değil, herhangi bir klasör içerisindeki dosya ve klasörleri almak istiyorsak bu sorguyu kullanabiliriz. Tabi öncesinde Root klasörünün ID bilgisini elde etmiş olmamız lazım. Bunun için aşağıdaki kodu kullanabiliriz.

/// <summary>
/// Drive root klasör id bilgisini döner
/// </summary>
/// <returns></returns>
public string GetRootID() {
    Google.Apis.Drive.v3.Data.File file = service.Files.Get("root").Execute();
    return file.Id;
}


Aşağıdaki gibi de metodlarımızı çağırabiliriz. 

string folderId= GetRootID();
string query = $"('{folderId}' in parents)";
List<Google.Apis.Drive.v3.Data.File> files = GetFiles(query);

Query kısmında dosyanın adına, türüne, oluşturulma veya değiştirilme tarihine göre sorgulamalar yapabiliriz. Hatta dosya yüklemesi yaparken sağlanan AppProperties özelliğine özel değerler oluşturup buradaki değerlere göre de sorgulamalar sağlayabiliyoruz. Bunu uygulamanın kaynak kodlarında da bulabileceksiniz. 


Klasör oluşturmak için de aşağıdaki methodu kullanabilirsiniz. 

/// <summary>
/// klasör oluşturur ve oluşturulan klasörü istenen detaylarla döner
/// </summary>
/// <param name="folderName">klasör adı</param>
/// <param name="parentId">hangi klasörün altına açılmak istenirse o klasörün id bilgisi verilir, boş geçilirse root'a açar</param>
/// <returns></returns>
public Google.Apis.Drive.v3.Data.File CreateFolder(string folderName, string parentId = null) {
    Google.Apis.Drive.v3.Data.File file = new Google.Apis.Drive.v3.Data.File {
        Name = folderName,
        MimeType = "application/vnd.google-apps.folder"
    };

    if (parentId != null) {
        file.Parents = new List<string> { parentId };
    }

    var request = service.Files.Create(file);
    request.Fields = "id, name, createdTime, modifiedTime, mimeType, description, size";
    var response = request.Execute();
    return response;
}


Bir dosya upload etmek istiyorsak o dosyanın türünü Mime Type olarak belirtmemiz gerekiyor. Bir dosyanın Mime Type bilgisini elde etmek için aşağıdaki methodu kullanabiliriz. 

/// <summary>
/// dosya yüklerken dosyanın türünü belirlemek için kullanılır, drive tarafından MimeType bilgisi istenir
/// </summary>
/// <param name="file">yüklenecek dosya</param>
/// <returns></returns>
private string GetMimeType(string file) {
    string mimeType = "application/unknown";
    string ext = System.IO.Path.GetExtension(file).ToLower();

    Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);

    if (regKey != null && regKey.GetValue("Content Type") != null) {
        mimeType = regKey.GetValue("Content Type").ToString();
    }

    return mimeType;
}


Aşağıdaki method ile de dosyamızı drive'a yükleyebiliriz. 

/// <summary>
/// dosya yükler
/// </summary>
/// <param name="file">yüklenecek dosya</param>
/// <param name="parentId">hangi klasöre yüklenecek, boş geçilirse DriveApiExample klasörü oluşturup oraya yükler</param>
/// <returns></returns>
public async Task<Google.Apis.Drive.v3.Data.File> UploadFile(string file, string parentId = null) {
    System.IO.FileInfo fileInfo = new System.IO.FileInfo(file);

    if (System.IO.File.Exists(file)) {
        Google.Apis.Drive.v3.Data.File body = new Google.Apis.Drive.v3.Data.File {
            Name = System.IO.Path.GetFileName(file),
            Description = "",
            AppProperties = new Dictionary<string, string> { { "customKey", "customValue" } },
            MimeType = GetMimeType(file)
        };

        if (!string.IsNullOrEmpty(parentId)) {
            body.Parents = new List<string> { parentId };
        }
        else {
            string folderId = CreateFolderAndGetID("DriveApiExample");
            body.Parents = new List<string> { folderId };
        }

        byte[] byteArray = System.IO.File.ReadAllBytes(file);

        using (var stream = new MemoryStream(byteArray)) {
            try {
                FilesResource.CreateMediaUpload request = service.Files.Create(body, stream, GetMimeType(file));
                request.SupportsTeamDrives = true;
                request.Fields = "id, name, createdTime, modifiedTime, mimeType, description, size";
                      
                request.ProgressChanged += (e) => {
                    if (e.BytesSent > 0) {
                        int progress = (int)Math.Floor((decimal)((e.BytesSent * 100) / byteArray.Length));
                        SetProgressValue(progress, "yükleniyor...");

                    }
                };

                request.ResponseReceived += (e) => {
                    SetProgressValue(100, "yüklendi");
                };

                SetProgressValue(0, "yükleniyor...");

                await request.UploadAsync();

                return request.ResponseBody;
            }
            catch (Exception ex) {
                throw new Exception(ex.Message);
            }
        }
    }
    else {
        throw new Exception("Dosya bulunamadı");
    }
}



Dosya silme metodunu ve uygulamadan görüntüler paylaştıktan sonra makaleyi noktalayalım. Dosya silmek için aşağıdaki basit kodu kullanabiliriz. 

/// <summary>
/// dosya siler
/// </summary>
/// <param name="fileId">silinecek dosya id</param>
/// <returns></returns>
public async Task<string> DeleteFile(string fileId) {
    return await service.Files.Delete(fileId).ExecuteAsync();
}


Uygulama üzerinden bazı işlem görüntüleri; 


Uygulamaya kaynak kodları ile birlikte buradan ulaşabilirsiniz. Makale içerisinde detayına inemediğim ve anlayamadığınız tüm eksik noktaları kaynak kodda bulabileceğinizi düşünüyorum. Aynı zamanda Google Drive API kullanımı haricinde win form uygulamalarında ListView kullanımını, sürükle bırak işlemlerini ve bir kaç detayı daha bilmeyenler öğrenmiş olacaklar. Okuyanlar ve API entegrasyonunu sağlayabilenler de yorumda bunu paylaşırlarsa çok memnun olurum.

Not olarak, uygulama içerisindeki GoogleDriveAPI sınıfı ufak çapta bir drive kütüphanesi oldu. Aynısını web ortamı için JavaScript ile de hazırlamayı hedefliyorum. Umarım en kısa zamanda vakit bulur ve onu da hazır edip sizlerle paylaşabilirim. 

Faydalı olması dileğiyle, bir sonraki yazıda görüşmek üzere :)


Etiketler

C#
Fahriye Gül Baştemir - 14.09.2020 13:36

Çok anlaşılır sade bir dille anlatılmış ve faydalı bir makale olmuş.. :) Ellerinize sağlık.. :)

Enes - 14.09.2020 14:15

Teşekkürler Fahriye :) ne kadar faydalı olduğunu yaptığın örnek üzerinden görmek daha iyi olacak :D

Mustafa Dikyar - 15.10.2020 00:09

Hocam ellerine sağlık. Güzel bir çalışma olmuş.

Enes - 15.10.2020 09:51

Çok teşekkürler hocam :)

Oğuzcan Genç - 17.10.2020 12:17

Hocam merhaba makale için çok teşekkürler. Buna benzer bir proje vardı elimde bu makale çok yardımcı olacak elinize sağlık.

Enes - 17.10.2020 13:14

Rica ederim Oğuzcan, yardımcı olmasına sevindim. Yorumun için teşekkürler :)

mesut - 19.10.2020 14:58

Merhaba, öncelikle emeğinize sağlık. yedekleme ile ilgili windows form app. bir uygulama yapıyorum ama projeyi derlediğimde browserda gmail açılıyor ve oradan izin vermemi istiyor. Bunu her seferinde sormaması için ne yapabilirim. Teşekkürler.

Enes - 19.10.2020 15:43

Merhaba, teşekkürler. Google hesabından bir kere izin vermeniz yeterli, doğrulama yaptıktan sonra bir daha sormayacaktır izin verdiğiniz hesap için. Ne zaman ki google hesap ayarlarınızdan uygulama iznini kaldırırsınız, o zaman tekrar izin isteyecektir sizden.

Hğseyin - 12.06.2021 02:14

Merhaba browserde gmail açılıyor ve 403 hatasına dusuyorum ızınleri tam olarak nerden çmak gerekıyor

Ferdi - 16.11.2020 15:22

Selamlar kolay gelsin kodu şimdi download ettim. Yalnız MainForm.cs dosyası 94 satırda await foreach ile başlayan bir yer var orada bir hata veriyor. Daha hiçbirşey yapmadan bu şekilde hata vermekte.

Enes - 16.11.2020 15:42

Selamlar, sanırım projeyi vs2017 ile açtınız. 94. satırda drivedan dosyaları çekerken IAsyncEnumarable kullanılıyor, bu özellik c# 8.0 ile gelen bir özellik ancak vs 2017de c# 8.0 desteği yok. projeyi vs 2019 ile sorunsuz açıp çalıştırabilirsiniz. Veya GoogleDriveAPI sınıfındaki GetFilesAsync metodunu c# 7.0 a uyarlayabilirsiniz. Orada yapmak istediğim driveda çok fazla dosya varsa async olarak 200er 200er çekmekti. siz async olarak tümünü çekip listeyebilirsiniz.

Enes - 16.11.2020 15:48

GetFilesAsync metodunu kaldırabilirsiniz ve GetFilesAsync yerine GetFiles metodunu da kullanabilirsiniz. Tüm dosyaları senkron olarak çeken metodu da eklemişim sınıfa. Bu durumda MainFormdaki GetList metodundaki async/await keywordlerini de kaldırabilirsiniz.

Burak - 11.12.2020 12:53

Merhaba. Makaleniz için teşekkür ederim. Çok faydası oldu. Başarılı şekilde entegrasyonu gerçekleştirdim. Fakat .exe yi windows görev zamanlayıcı ile tetikleyerek çalıştırdığım zaman google api bağlantısı başarısız oluyor. Sebebi ne olabilir? Manuel olarak çalıştırdığımda sorun yok. Teşekkür ederim şimdiden

Enes - 12.12.2020 19:37

Merhaba, yorumunuz için teşekkür ederim. Uygulamayı Windows Görev Zamanlayıcı ile tetikleyerek çalıştırdığımda herhangi bir problem olmadı. Daha önceden bir kez authentication sağlanmışsa bir problem olmaması lazım, tabi eğer sorun bununla ilgiliyse. Bu değilse de görev tetiklendiğinde masaüstü veya oturum açık durumda mı, bu gibi durumlardan etkilenmesi de olası. Görev zamanlayıcı ile başlatma sebebiniz nedir bu arada?

Burak - 19.12.2020 11:29

Sunucu yedekleme yazılımı geliştirdim ve sunucularımızdaki datayı google drive a yedekliyorum bunun için de görev zamanlayıcı ile belli periyotlarda çalıştırmam gerekiyordu. Sorunu çözdüm bu arada. Uygulama izni vermediğim için program kendini kapatıyordu sonradan farkettim. Şuan yaşamakta olduğum başka bir sorun var. Google drive a api ile 2 gb dan büyük dosya yükleyemiyorum. Daha doğrusu bu sorun google api servisi ile ilgili değil şuan için. Drive upload yapmadan önce dosyayı MemoryStream nesnesine atıyordum. MemoryStream max size 2 Gb kabul ettiği için hata aldım ve bunu düzeltmek için FileStream kullanmaya çalışıyorum. Fakat henüz başarabilmiş değilim. Bu konuda bilginiz var mıdır? Teşekkür ederim.

Enes - 19.12.2020 16:01

Tekrar merhaba, projeyi kaynak kodlarıyla github üzerinden paylaşmıştım, FileStream revizesini de commit etmiştim. güncel repoyu indirip inceleyebilirsiniz. https://github.com/enestas/google-drive-api-using

Bahri - 03.01.2021 16:04

Merhaba, yapmış olduğunuz programı indirip hemen kullanmamız mümkün mü?

Enes - 03.01.2021 19:44

Merhaba, github üzerinden açık kaynak olarak paylaştım, oradan indirip kullanabilirsiniz elbette. Fakat öncesinde google developer console üzerinden authentication için key oluşturmanız gerekiyor, sormak istediğiniz buysa eğer.

Ahmet Güneş - 19.05.2021 12:40

Elinize sağlık, gayet güzel bir uygulama oldu. Fırsat bulursam kendime göre ufak tefek görsel değişiklikler yapabilirim. Ben bu uygulamayı bir süredir yazılımcı arkadaşlarımla konuşuyordum ama açıkçası cesaret edebilen olmadı, bende daha yeni yazılım öğrendiğim için ilerleyemedim. ama sizin sayenizde başarılı bir entegrasyon gerçekleştirdim. Özellikle 5000 den fazla pdf dosyamı daha pratik yönetmek okumak vs amacıyla kullanmak istediğim için birazcık geliştirmem gerek. Tabi buna da zaman lazım. Bakalım ben aktif bir Gdrive PDF kütüphanesi yapmaya çalışıyorum. pdflerimi dilediğim şekilde listelemek, ön izlemek, hatta bi kaç ek bilgi ekleyebilmek, hatta mümkünse direk okuyup içinde arama yapabilmek vs. biraz fazla şey istiyorum belki ama hayali bile heyecanlandırıyor beni :D teşekkürler tekrar.

Enes - 22.05.2021 23:22

Rica ederim, amacınıza hizmet eden bir kaynak oluşturabilmiş olmam beni ayrıca memnun etti, teşekkürler yorumunuz için :)

Yorum Yap