Upload Media

Several API methods support uploading media in addition to a regular body. In that case, the regular request method is overloaded to get an additional Stream to upload.

Overview

For any Stream you wish to upload, you should use resumable media upload, which allows streams to be uploaded in smaller chunks. This is especially useful if you are transferring large files, and the likelihood of a network interruption or some other transmission failure is high. It can also reduce your bandwidth usage in the event of network failures because you don't have to restart large file uploads from the beginning.

ResumableMediaUpload

Resumable Media Upload has been a feature in the Google API .NET client library since 1.2.0-beta. The Google API-specific libraries contain convenience methods for interacting with this feature.

The resumable media upload protocol is described, for example, on the media upload page for the Drive API. The main class of interest is ResumableUpload. In this implementation, the media content is uploaded in chunks.

The default chunk size is 10MB, but you can change it by setting the ChunkSize property on the request to any multiple of 256KB. If a server error is encountered in a request then exponential backoff policy is used to resend the bytes that were not successfully uploaded. By default, exponential backoff is enabled for each client request. You can change the default behavior when you construct a new service object by changing the DefaultExponentialBackOffPolicy property on BaseClientService.Initializer and/or setting the HttpClientInitializer property to your own implementation of IConfigurableHttpClientInitializer that adds some backoff policy.

The methods that support media upload are identified in the reference documentation for the API-specific documentation. For these API methods, convenience Upload and UploadAsync methods are added. Those methods take a Stream to upload and its content type as parameters.

Make sure that the position of the stream you upload is 0, otherwise you will receive an error, such as "System.InvalidOperationException: The given header was not found".

Note that due to the behavior of the framework's HttpClient class, if the upload times out, a TaskCanceledException is thrown. If you see this exception, consider manually increasing the Timeout property in the client used by your service object.

Sample Code

// Create the service using the client credentials.
var service = new DriveService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential,
    ApplicationName = "Application_Name"
});

using var uploadStream = System.IO.File.OpenRead("Local_File_Name");

// Create the File resource to upload.
Google.Apis.Drive.v3.Data.File driveFile = new Google.Apis.Drive.v3.Data.File
{
    Name = "Drive_File_Name"
};
// Get the media upload request object.
FilesResource.CreateMediaUpload insertRequest = service.Files.Create(
    driveFile, uploadStream, "image/jpeg");

// Add handlers which will be notified on progress changes and upload completion.
// Notification of progress changed will be invoked when the upload was started,
// on each upload chunk, and on success or failure.
insertRequest.ProgressChanged += Upload_ProgressChanged;
insertRequest.ResponseReceived += Upload_ResponseReceived;

await insertRequest.UploadAsync();

static void Upload_ProgressChanged(IUploadProgress progress) =>
    Console.WriteLine(progress.Status + " " + progress.BytesSent);

static void Upload_ResponseReceived(Google.Apis.Drive.v3.Data.File file) =>
    Console.WriteLine(file.Name + " was uploaded successfully");