Download files from Google Drive with C# 10


Please Share

google drive Are you working on an application that needs download files from a users Google Drive account. I am going to show you how to do that using C# and the Google .Net Client library.

Prerequisite

The first thing we will need to do is import the Google Drive API v3 NuGet package

Install-Package Google.Apis.Drive.v3

Authenticate

File list is private data which means it is owned by a user. In order to access it you must be authenticated to that user. We also need a users permission to download the file once we have listed it.


        /// <summary>
        /// This method requests Authentcation from a user using Oauth2.  
        /// Credentials are stored in System.Environment.SpecialFolder.Personal
        /// Documentation https://developers.google.com/accounts/docs/OAuth2
        /// </summary>
        /// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
        /// <param name="userName">Identifying string for the user who is being authentcated.</param>
        /// <returns>DriveService used to make requests against the Drive API</returns>
        public static DriveService AuthenticateOauth(string clientSecretJson, string userName)
        {
            try
            {
                if (string.IsNullOrEmpty(userName))
                    throw new ArgumentNullException("userName");
                if (string.IsNullOrEmpty(clientSecretJson))
                    throw new ArgumentNullException("clientSecretJson");
                if (!File.Exists(clientSecretJson))
                    throw new Exception("clientSecretJson file does not exist.");

                // These are the scopes of permissions you need. It is best to request only what you need and not all of them
                string[] scopes = new string[] { DriveService.Scope.DriveReadonly};         	//View the files in your Google Drive                                                 
                UserCredential credential;
                using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
                {
                    string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
                    credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);

                    // Requesting Authentication or loading previously stored authentication for userName
                    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
                                                                             scopes,
                                                                             userName,
                                                                             CancellationToken.None,
                                                                             new FileDataStore(credPath, true)).Result;
                }

                // Create Drive API service.
                return new DriveService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive Oauth2 Authentication Sample"
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine("Create Oauth2 account DriveService failed" + ex.Message);
                throw new Exception("CreateServiceAccountDriveFailed", ex);
            }
        }

File.List

My tutorial on searching for files with the file.list method contains the code you will need to list files. I wont be adding that here i recommend you check out that tutorial first. Search files with Google Drive with C#.


Download File

Downloading a file is done with the Files.get method and a media downloader from the client library to download your file.


 private static void DownloadFile(Google.Apis.Drive.v3.DriveService service, Google.Apis.Drive.v3.Data.File file, string saveTo)
        {

            var request = service.Files.Get(file.Id);
            var stream = new System.IO.MemoryStream();

            // Add a handler which will be notified on progress changes.
            // It will notify on each chunk download and when the
            // download is completed or failed.
            request.MediaDownloader.ProgressChanged += (Google.Apis.Download.IDownloadProgress progress) =>
               {
                   switch (progress.Status)
                   {
                       case Google.Apis.Download.DownloadStatus.Downloading:
                           {
                               Console.WriteLine(progress.BytesDownloaded);
                               break;
                           }
                       case Google.Apis.Download.DownloadStatus.Completed:
                           {
                               Console.WriteLine("Download complete.");
                               SaveStream(stream, saveTo);
                               break;
                           }
                       case Google.Apis.Download.DownloadStatus.Failed:
                           {
                               Console.WriteLine("Download failed.");
                               break;
                           }
                   }
               };
            request.Download(stream);

        }

Assuming that the file download succeeds then we save the file to the hard drive.


private static void SaveStream(System.IO.MemoryStream stream, string saveTo)
{
     using (System.IO.FileStream file = new System.IO.FileStream(saveTo, System.IO.FileMode.Create, System.IO.FileAccess.Write))
        {
         stream.WriteTo(file);
         }
}

Putting it all together

By using file.list I can search for the files that I am interested in then loop though each one downloading it.


// Connect to Google
var service = GoogleSamplecSharpSample.Drivev3.Auth.Oauth2Example.AuthenticateOauth(@"[Location of the Json cred file]", "test");
//List the files with the word 'make' in the name.
var files = DriveListExample.ListFiles(service, 
                 new DriveListExample.FilesListOptionalParms() { Q = "name contains 'Make'" , Fields= "*"});
foreach (var item in files.Files)
     {
     // download each file
     DriveDownload.Download(service, item, string.Format(@"C:\FilesFromGoogleDrive\{0}",item.Name));
      }

Conclusion

Downloading files from Google drive can be quite useful using media downloader makes it quite simple. I have considered setting up a windows service to mirror my google drive account down to my PC and back up to Google Drive. This way i can keep the data backed up and in sync.

Please Share


Linda Lawton

About Linda Lawton

My name is Linda Lawton I have more than 20 years experience working as an application developer and a database expert. I have also been working with Google APIs since 2012 and I have been contributing to the Google .Net client library since 2013. In 2013 I became a a Google Developer Experts for Google Analytics.


Leave a comment

Your email address will not be published. Required fields are marked *

10 thoughts on “Download files from Google Drive with C#

  • Manuel

    Hello Linda!
    How does this work with the file.export method? I used: var request = service.Files.Export(fileId, “application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”);. Shouldnt the file get an extension by itsfel then or am I mistaken?

      • Manuel

        Hello Linda, its been a while but today I noticed a problem. When downloading larger files (well 80MB>, isnt that large) the downlaod wont complete correctly. I tested it with several zip files: 100mb, 200mb, 512mb and 1gb. 100mb and 200mb just work fine but the other two dont. When trying to download the 512mb zip file it stops at about 320 000 000 bytes, writes “Downlaod complete” in the console and goes on to the next file. Obviously the file didnt get saved on my HDD.
        Do you have any clue what could be causing this?

          • Manuel

            Actually the problem is a bit different now. I didn’t change much in my code but for now this works, except files that are larger than 2GB (stops at about 2040MB). I read that this seems to be a common issue because this is a limitation at googles site, right? There must be a way to bypass that, except for installing the desktop app.

          • Linda Lawton
            Linda Lawton Post author

            I am not sure if its a limitation but its something i have heard of. The Google drive api doesn’t appear to like large files. Make sure you are using resumable download or upload then you can pick up where it failed.