How to upload a file to Google Drive with C# .net 2


Please Share

Google Drive API V3

Google Drive API V3

This Tutorial was completely rewritten in April, 2021

Uploading files to the Google Drive API V3 can be a little confusing in the beginner. I have seen a lot of questions and issues related to it on Stack Overflow over the years. These issues normally stem from the fact that creating a file is actually done in two parts, the first being creating the metadata that being the name, description
and mimeType. Once the file is created with its meta data only then should we upload the file in the form of a file stream. If you fail to create the file metadata then you will upload a file that is unnamed.

The second issue comes when you try to update a file that already exists on Google Drive, most people just try to use the same method that being file.create. Then they are confused when a second file rather than updating and overwriting the existing file which is what you actually want to do.

In this case you should be using the file update method and not the file create method. Then again the confusion comes in with the fact that its two part
you can update the file metadata, and then update the file itself by uploading a file stream. The final issue with file.update comes in with the fact that
update is in the form of HTTP patch methodology and not all of the properties of a file object are actually writeable.
So you may end up getting an error stating that the field you are trying to update is not actually writeable.

Setup

I thought this time we would look into using a service account. Think of a service account as a dummy user. You can pre authorize a service account granting it access to your data. So i can take the service accounts email address and share with it a directory on my Google Drive account then it will have access
to upload to that directory on my google drive account. It’s that simple there will be no need for user interaction and a consent screen to popup.

You should consider using a service account if you are going to be accessing private data that you the developer own, if you are going to be accessing
data that belongs to another user then you should be using Oauth2.

So you will need to go to Google developer console and create a new service account. Download the json key file and don’t forget to enable the google drive api
under libraires. If you have any issues I have a video which you can go check out and it will walk you through creating
service account credential key file.

How to create Google Oauth2 Service account credentials.

Create .net core console application

For this i am going to create a .net core console application, but you can use service accounts, with libraries or with asp .net core its up to you which type
of project you create but for this example we are going to keep it simple and just use a console app.

you will need to include the google.apis.drive.v3 nuget package.

Add constant

At the top of my program class i am going to create a couple of constants.

The first is the path to the credentials.json file we downloaded from google developer console, as always don’t share your credentials with anyone these should
be stored save and secure for only your team to access.

I will need another constant for the service account email address, you can get this from google developer console or you can just open the key file in a text editor
and you will find it there its the one that contains an @ and looks kind of like an email address.

In my project i have created a simple text document called Test hello.txt remember to set this file to copy always under its properties. So i have added the name
as a constant here just for consistency.

Finally i have a directory id constant which is the file id of the directory on my google drive account which i shared with the service account. The easiest way
to find the directory name here is to do a file.list and it will list all of the files that the service account has access to it will also return the directory
that we shared with it so we can get the file id we will need to upload our files.

private const string PathToServiceAccountKeyFile = @"C:\Youtube\dev\ServiceAccountCred.json";
private const string ServiceAccountEmail = "driveuploadtest@testapikey-305109.iam.gserviceaccount.com";
private const string UploadFileName = "Test hello.txt";
private const string DirectoryId = "10krlloIS2i_2u_ewkdv3_1NqcpmWSL1w";

Authorize service account

Ok now we we will need to load the credentials into our application. We simply load the credentials key file and set which scope we will be using. Due to the fact that we will
be uploading a file we will need write access to the drive account. so we will be using the drive scope, to attain full access to the users drive account.

// Load the Service account credentials and define the scope of its access.
var credential = GoogleCredential.FromFile(PathToServiceAccountKeyFile)
                .CreateScoped(DriveService.ScopeConstants.Drive);

create drive service

Finally we will create our drive service. All calls to the Google drive api will be run though the drive service object.

// Create the  Drive service.
var service = new DriveService(new BaseClientService.Initializer()
    {
    HttpClientInitializer = credential
    });

Create a new file on Google Drive and upload it

Remember I mentioned the metadata of the file. If you dont set the files metadata then the file will upload with a name of unnamed. So for the very minimum we
should set the name of the file. i am also going to set parents. If i don’t set parents the file will be uploaded to the root folder of the service account.

// Upload file Metadata
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
    {
    Name = "Test hello uploaded.txt",
    Parents = new List() {"10krlloIS2i_2u_ewkdv3_1NqcpmWSL1w"}
    };

Remember i mentioned that a service account is a dummy user well this dummy user actually has its own google drive account and you can upload files to it.
By setting parents we well be uploading the file to the directory i shared with the service account.

Now in order to upload the file itself we will need to load it into a filestream. Once we have done that we can call the service.file.create method
and pass it the file metadata, and the filestream itself. Finally we will call upload async to upload the file to google drive.

string uploadedFileId;
// Create a new file on Google Drive
await using (var fsSource = new FileStream(UploadFileName, FileMode.Open, FileAccess.Read))
      {
      // Create a new file, with metadata and stream.
      var request = service.Files.Create(fileMetadata, fsSource, "text/plain");
      request.Fields = "*";
      var results = await request.UploadAsync(CancellationToken.None);

      if (results.Status == UploadStatus.Failed)
         {
         Console.WriteLine($"Error uploading file: {results.Exception.Message}");
         }

          // the file id of the new file we created
          uploadedFileId = request.ResponseBody?.Id;
      }

The response body on our request will contain the id of the newly created file.

If we check google drive sure enough we have a file there now. Remember if you didn’t add parents that the file will be uploaded to the service accounts google drive account and you won’t be able to see it unless you do a files.list

Updating an existing file on Google Drive

Lets try to update the file we just created.

Remember i mentioned that we still need metadata. I create a new file object and i can add a name to it. If you don’t actually want to update the metadata you could
just pass the same name and all would work. If you do actually want to change something in the metadata it is here you would do that. Just remember that
not all of the fields are writable Id for example is not writeable.

// Let's change the files name.
// Note: not all fields are writeable watch out, you cant just send uploadedFile back.
var updateFileBody = new Google.Apis.Drive.v3.Data.File()
    {
     Name = "update.txt"
     };

I thought I would make a quick change to the file itself by adding some text so that we can see that it is in fact uploaded.

// Let's add some text to our file.
await File.WriteAllTextAsync(UploadFileName, "Text changed in file.");

Then we again load the file stream and this time instead of calling files.create we will call files.update and pass it the updated file metadata, the file id of
the file we are trying to update and the stream. and again call updateasync

// Then upload the file again with a new name and new data.
await using (var uploadStream = new FileStream(UploadFileName, FileMode.Open, FileAccess.Read))
     {
      // Update the file id, with new metadata and stream.
     var updateRequest = service.Files.Update(updateFileBody, uploadedFile.Id, uploadStream, "text/plain");
     var result = await updateRequest.UploadAsync(CancellationToken.None);

     if (result.Status == UploadStatus.Failed)
     {
     Console.WriteLine($"Error uploading file: {result.Exception.Message}");
     }
  }

Now when we check Google Drive again we can see sure enough our file name is updated and the contents have been updated as well.

Conclusion

Uploading files with Google Drive api can be a little confusing you just need to remember that if you are uploading to an existing file you will need to use
update and if you are creating a new file you will need to use update. Also remember when updating that not all fields in the file metadata are writable.

Please Share


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 *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 thoughts on “How to upload a file to Google Drive with C# .net

  • Evry1falls

    I’m confused about something concerning Google Drive Api v3. This is a scenario I use now :
    WinForm application project, VS2015
    Two Forms
    [Form1 to authenticate user to use my Google Drive Folder(ThisFolder)]
    [Form2 to upload files to my google drive folder(ThisFolder)]
    [Form1]
    I use a native code to receive access Token [using loopback url] and save it to User settings file (My.Settings.accesstoken=received_access_token)
    [Form2]
    When I use your Example, it still opens web browser to authenticate user before uploading.
    and uploading is done.
    My problem is that I don’t want to re-authenticate the user each time the user tries to upload a file.

    • Linda Lawton Post author

      If your allowing them to upload to your drive account then you should be using a service account. Which wouldn’t request authorization.

      Here is an example as well.