Are you working on an application where you would like to download large files from Google drive? This simple tutorial will show you how to download large files by chunks.
Setup
The first thing you will need to do is create a new project on Google developer console. For this project i will be using a console application so we will create a native client. Note this code will NOT work for a web browser application.
You will also need the NuGet package Install-Package Google.Apis.Drive.v3 you will also need to grab my sample class for authencating to Google drive Oauth2Authentication.cs
Code
class Program
{
private const string _pathToCreds = @"C:\creds\client_secret.json";
async static Task Main(string[] args)
{
var service = auth.Oauth2Example.GetDriveService(_pathToCreds, "test",
new[] {Google.Apis.Drive.v3.DriveService.Scope.Drive});
var request = service.Files.List();
request.Q = "name='reallybigfile.zip'";
var result = await request.ExecuteAsync();
foreach (var file in result.Files)
{
await DownloadFile(file.Id, service);
}
Console.WriteLine("Hello World!");
}
public static async Task DownloadFile(string fileId, DriveService service)
{
const int KB = 0x400;
var chunkSize = 256 * KB; // 256KB;
var fileRequest = service.Files.Get(fileId);
fileRequest.Fields = "*";
var fileResponse = fileRequest.Execute();
var exportRequest = service.Files.Export(fileResponse.Id, fileResponse.MimeType);
var client = exportRequest.Service.HttpClient;
//you would need to know the file size
var size = fileResponse.Size;
await using var file = new FileStream(fileResponse.Name, FileMode.OpenOrCreate, FileAccess.ReadWrite);
file.SetLength((long) size);
var chunks = (size / chunkSize) + 1;
for (long index = 0; index < chunks; index++)
{
var request = exportRequest.CreateRequest();
var from = index * chunkSize;
var to = @from + chunkSize - 1;
request.Headers.Range = new RangeHeaderValue(@from, to);
var response = await client.SendAsync(request);
if (response.StatusCode != HttpStatusCode.PartialContent && !response.IsSuccessStatusCode) continue;
await using var stream = await response.Content.ReadAsStreamAsync();
file.Seek(@from, SeekOrigin.Begin);
await stream.CopyToAsync(file);
}
}
}
}
Conclusion
Simple download gives us a method for downloading large files from google drive.
Hi Linda,
I am always getting 403 exception when firing sendAsync. Please suggest what is be the problem?
Which 403 exception?
oops – re-tested my code, and there was a bug (it was downloading the getfile metadata and saving that over and over). Here’s the correct code sample:
const int KB = 0x400;
var chunkSize = 10240 * KB; // 10240KB (10MB);
var fileRequest = _service.Files.Get(fileResource.Id);
fileRequest.Fields = “*”;
fileRequest.SupportsAllDrives = true;
var fileResponse = fileRequest.Execute();
var client = fileRequest.Service.HttpClient;
//you would need to know the file size
var size = fileResponse.Size;
await using var file = new FileStream(fileResponse.Name, FileMode.OpenOrCreate, FileAccess.ReadWrite);
file.SetLength((long)size);
var chunks = (size / chunkSize) + 1;
for (long index = 0; index < chunks; index++)
{
var from = index * chunkSize;
var to = @from + chunkSize – 1;
var range = new RangeHeaderValue(@from, to);
//VALIDATE SUCCESSFUL REQUEST
var request = fileRequest.CreateRequest();
request.Headers.Range = range;
var response = await client.SendAsync(request);
if (response.StatusCode != HttpStatusCode.PartialContent && !response.IsSuccessStatusCode)
{
//ERROR OCURRED
Console.WriteLine(response.ToString());
continue;
}
//IF NO ERRORS, PERFORM DOWNLOAD RANGE
Console.WriteLine($"ChunkIndex: {index}; File Size: {size}; Bytes Downloaded: {from} ({Convert.ToDecimal(from)/(1024.0m * 1024.0m)}) MB; ");
file.Seek(@from, SeekOrigin.Begin);
await fileRequest.DownloadRangeAsync(file, range);
Hi Linda,
I’m trying to implement this solution, but I am also getting a 403 (Forbidden) error.
It’s pretty ambiguous, I’m trying to get additional data to tell me the reason:
StatusCode: 403, ReasonPhrase: ‘Forbidden’, Version: 1.1, Content: System.Net.Http.DecompressionHandler+GZipDecompressedContent, Headers:
{
Vary: Origin
Vary: X-Origin
Date: Fri, 21 Aug 2020 18:21:12 GMT
Cache-Control: max-age=0, private
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors ‘self’
X-XSS-Protection: 1; mode=block
Server: GSE
Alt-Svc: h3-29=”:443″; ma=2592000,h3-27=”:443″; ma=2592000,h3-T050=”:443″; ma=2592000,h3-Q050=”:443″; ma=2592000,h3-Q046=”:443″; ma=2592000,h3-Q043=”:443″; ma=2592000,quic=”:443″; ma=2592000; v=”46,43″
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
Expires: Fri, 21 Aug 2020 18:21:12 GMT
}
I recommend posting your cod over on stack overflow i will have a look