Search code examples
asp.netgoogle-drive-apigoogle-api-console

download file from google drive using asp.net


I am trying download file from google drive using the code below:

     public static Boolean downloadFile(string downloadurl, string _saveTo)
        {

            if (!String.IsNullOrEmpty(downloadurl))
            {
                try
                {
                  var x = service.HttpClient.GetByteArrayAsync(downloadurl);
                    byte[] arrBytes = x.Result;
                    System.IO.File.WriteAllBytes(_saveTo, arrBytes);
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine("An error occurred: " + e.Message);
                    return false;
                }
            }
            else
            {
                // The file doesn't have any content stored on Drive.
                return false;
            }
        }

On debugging the above code throwing exception as below:

?service.HttpClient.GetByteArrayAsync(downloadurl)
Id = 10, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
    AsyncState: null
    CancellationPending: false
    CreationOptions: None
    Exception: null
    Id: 10
    Result: null
    Status: WaitingForActivation

I am trying to do it from my Service account created using Google API Console.

and the exception detail is as follows:

System.NullReferenceException was caught
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=System.Net.Http
  StackTrace:
       at System.Net.Http.Headers.HttpRequestHeaders.AddHeaders(HttpHeaders sourceHeaders)
       at System.Net.Http.HttpClient.PrepareRequestMessage(HttpRequestMessage request)
       at System.Net.Http.HttpClient.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
       at System.Net.Http.HttpClient.GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
       at System.Net.Http.HttpClient.GetContentAsync[T](Uri requestUri, HttpCompletionOption completionOption, T defaultValue, Func`2 readAs)
       at System.Net.Http.HttpClient.GetByteArrayAsync(Uri requestUri)
       at System.Net.Http.HttpClient.GetByteArrayAsync(String requestUri)

Solution

  • Code using the Google .net client library

    Service account:

    string[] scopes = new string[] {DriveService.Scope.Drive}; // Full access
    
    var keyFilePath = @"c:\file.p12" ;    // Downloaded from https://console.developers.google.com
    var serviceAccountEmail = "xx@developer.gserviceaccount.com";  // found https://console.developers.google.com
    
    //loading the Key file
    var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
    var credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) {
                                                       Scopes = scopes}.FromCertificate(certificate));
    

    create drive service

    var service = new DriveService(new BaseClientService.Initializer() {HttpClientInitializer = credential,
                                                                                ApplicationName = "Drive API Sample",});
    

    You can use files.list to list all of the files on drive.

    FilesResource.ListRequest request = service.Files.List();
    request.Q = "trashed=false";
    title = 'hello'
    FileList files = request.Execute();
    

    loop though the items returned find the file you want it is a file resource you can pass it to the following method to down load your file

    /// <summary>
            /// Download a file
            /// Documentation: https://developers.google.com/drive/v2/reference/files/get
            /// </summary>
            /// <param name="_service">a Valid authenticated DriveService</param>
            /// <param name="_fileResource">File resource of the file to download</param>
            /// <param name="_saveTo">location of where to save the file including the file name to save it as.</param>
            /// <returns></returns>
            public static Boolean downloadFile(DriveService _service, File _fileResource, string _saveTo)
            {
    
                if (!String.IsNullOrEmpty(_fileResource.DownloadUrl))
                {
                    try
                    {
                        var x = _service.HttpClient.GetByteArrayAsync(_fileResource.DownloadUrl );
                        byte[] arrBytes = x.Result;
                        System.IO.File.WriteAllBytes(_saveTo, arrBytes);
                        return true;                  
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("An error occurred: " + e.Message);
                        return false;
                    }
                }
                else
                {
                    // The file doesn't have any content stored on Drive.
                    return false;
                }
            }
    

    code ripped from Google drive authentication C#