Posted in:

Closely related to my recent post about how to list and download the contents of a GitHub repo in C#, I also wanted to be able to list the files in a publicly shared Google Drive folder and download them from C#.

There is a Google Drive API we can use for this purpose, but first we need an API key.

You can generate one for use with your application at the Google Developer Console. Obviously you should avoid exposing this key to the end users of your application.

Now we need the folder id of the Google Drive folder that's been shared with you. Usually you'll receive a sharing URL that looks something like this, with the folder id as part of the URL:

https://drive.google.com/drive/folders/4wj98k3bbQsLRuiWm-PrQlRfkrEP6lbNg?usp=sharing

Let's see some code to list the files in the folder. We can do that with a call to the /drive/v3/files endpoint, passing in a query for any files that have the folder id as one of their parents. The results are paged, so we need to keep calling it until we no longer get a next page token.

The resulting JSON object has an array of files each of which has an id and name as well as a kind (which is usually drive#file) and a mimeType. In my code sample I just print out the id and name of each file in the folder.

var httpClient = new HttpClient();
var publicFolderId = "4wj98k3bbQsLRuiWm-PrQlRfkrEP6lbNg";
var googleDriveApiKey = "Your Google Drive API key";
var nextPageToken = "";
do
{
    var folderContentsUri = $"https://www.googleapis.com/drive/v3/files?q='{publicFolderId}'+in+parents&key={googleDriveApiKey}";
    if (!String.IsNullOrEmpty(nextPageToken))
    {
        folderContentsUri += $"&pageToken={nextPageToken}";
    }
    var contentsJson = await httpClient.GetStringAsync(folderContentsUri);
    var contents = (JObject)JsonConvert.DeserializeObject(contentsJson);
    nextPageToken = (string)contents["nextPageToken"];
    foreach (var file in (JArray)contents["files"])
    {
        var id = (string)file["id"];
        var name = (string)file["name"];
        Console.WriteLine($"{id}:{name}");
    }
} while (!String.IsNullOrEmpty(nextPageToken));

And what if you want to download the contents of a file? You can do this by constructing a URL with the file id as shown in the code snippet below. This works for publicly shared files - no authentication is needed.

Here's an example of downloading the contents as a string:

var id = // the id of the file you want to download;
var downloadUri = $"https://drive.google.com/uc?export=download&id={id}";
var contents = await httpClient.GetStringAsync(downloadUri);

Comments

Comment by Murat K. Gungor

Thank you for the great post.
First part worked perfectly. But for downloading a file, when I copy/paste the downloadUri to Chrome it works, I can download the file manually but when I try other browser where I did not log in - it redirects to google login screen, even though the folder has been shared "Anyone with the link". As expected when I try to do with code, html content comes as string via this command (the login html) httpClient.GetStringAsync(downloadUri); not the file content
Question: I could not figure it out, any help would be appreciated.
For this code:
This package is needed - FYI
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Murat K. Gungor