Skip to content

Files Client

Gunpal Jain edited this page Nov 15, 2026 · 4 revisions

FileClient works with the Gemini API Files service. It can upload files (from a path or a stream), register Google Cloud Storage objects, read metadata, list, delete, download generated files (such as videos) and wait for a file to finish processing. Uploaded files can then be referenced in prompts.

Package: Google_GenerativeAI. Namespace: GenerativeAI.Clients.

The Files API is a Gemini Developer API feature. On Vertex AI, reference files in Cloud Storage (gs://...) or send them inline instead (see Multimodal Features). DownloadFileAsync and RegisterFilesAsync throw NotSupportedException on Vertex AI.

Getting a FileClient

From GeminiModel.Files

GeminiModel (created with GoogleAi.CreateGeminiModel) comes with a FileClient in its Files property, so you don't need to create one:

using GenerativeAI;
using GenerativeAI.Clients;
using GenerativeAI.Types;

var geminiModel = new GoogleAi("YOUR_API_KEY").CreateGeminiModel(GoogleAIModels.Gemini38Flash);

var remoteFile = await geminiModel.Files!.UploadFileAsync(
    "path/to/my/file.txt",
    progressCallback: progress => Console.WriteLine($"Upload Progress: {progress:F2}%"));

Console.WriteLine($"File uploaded successfully. Remote File Name: {remoteFile.Name}");

GeminiModel also has shortcuts: UploadFileAsync(filePath, progressCallback), GetFileAsync(fileId) and AwaitForFileStateActive(file, maxSeconds).

Standalone

var fileClient = new FileClient(new GoogleAIPlatformAdapter("YOUR_API_KEY"));

1. Uploading Files

From a file path (UploadFileAsync)

The display name is the file name without its extension, and the MIME type is detected from the extension.

try
{
    RemoteFile remoteFile = await fileClient.UploadFileAsync(
        "path/to/my/video.mp4",
        progressCallback: progress => Console.WriteLine($"Upload Progress: {progress:F2}%"));

    Console.WriteLine($"Uploaded: {remoteFile.Name} ({remoteFile.Uri})");
}
catch (Exception ex)
{
    Console.WriteLine($"Error uploading file: {ex.Message}");
}

From a stream (UploadStreamAsync)

using var fileStream = File.OpenRead("path/to/my/file.txt");

RemoteFile remoteFile = await fileClient.UploadStreamAsync(
    fileStream,
    displayName: "my_uploaded_file",
    mimeType: "text/plain",
    progressCallback: progress => Console.WriteLine($"Upload Progress: {progress:F2}%"));

The stream must report its Length, and the MIME type must be in FilesConstants.SupportedMimeTypes.

2. Registering Cloud Storage Files (RegisterFilesAsync)

Registers existing gs:// objects with the Files service, so you can use them in prompts without uploading them again. The SDK needs an OAuth access token with read access to the objects. If you don't pass accessToken, it uses the platform's token, authenticator or Application Default Credentials.

RegisterFilesResponse registered = await fileClient.RegisterFilesAsync(
    new[] { "gs://my-bucket/report.pdf", "gs://my-bucket/chart.png" },
    accessToken: null,                // optional OAuth token
    quotaProjectId: "my-gcp-project"); // optional, sent as x-goog-user-project

foreach (var file in registered.Files ?? new List<RemoteFile>())
    Console.WriteLine($"{file.Name} -> {file.Uri} (source: {file.Source})");

Registered files have Source == Source.REGISTERED.

3. Getting File Metadata (GetFileAsync)

RemoteFile remoteFile = await fileClient.GetFileAsync("files/your-file-id");
Console.WriteLine($"File Name: {remoteFile.Name}, Size: {remoteFile.SizeBytes}, State: {remoteFile.State}");

RemoteFile properties include Name, DisplayName, MimeType, SizeBytes, CreateTime, UpdateTime, ExpirationTime, Sha256Hash, Uri, DownloadUri, State (PROCESSING, ACTIVE, FAILED), Source (UPLOADED, GENERATED, REGISTERED), Error and VideoMetadata.

4. Listing Files (ListFilesAsync)

var response = await fileClient.ListFilesAsync(pageSize: 20); // max 100

foreach (var file in response.Files ?? new List<RemoteFile>())
    Console.WriteLine($"File Name: {file.Name}, Display Name: {file.DisplayName}");

if (!string.IsNullOrEmpty(response.NextPageToken))
{
    var next = await fileClient.ListFilesAsync(pageSize: 20, pageToken: response.NextPageToken);
}

5. Deleting Files (DeleteFileAsync)

await fileClient.DeleteFileAsync("files/your-file-id");

6. Downloading Generated Files (DownloadFileAsync, DownloadFileToPathAsync)

Files the API generated, for example videos from Veo, can be downloaded. Files you uploaded can't. Check RemoteFile.DownloadUri or RemoteFile.Source == Source.GENERATED first.

// Into memory
byte[] bytes = await fileClient.DownloadFileAsync("files/generated-file-id");

// From a RemoteFile (throws ArgumentException if it has no DownloadUri)
byte[] bytes2 = await fileClient.DownloadFileAsync(remoteFile);

// Stream to any writable stream without buffering the whole file
await using (var output = File.Create("video.mp4"))
{
    await fileClient.DownloadFileAsync(remoteFile, output);
}

// Straight to a local path
await fileClient.DownloadFileToPathAsync("files/generated-file-id", "video.mp4");

The name can be files/{id}, {id}, or the file's download or URI URL.

7. Waiting for a File to Become Active (AwaitForFileStateActiveAsync)

Video and other large files are processed after upload. Wait for the file to become ACTIVE before you use it in a prompt:

var remoteFile = await fileClient.UploadFileAsync("lecture.mp4");
await fileClient.AwaitForFileStateActiveAsync(remoteFile, maxSeconds: 300, cancellationToken: CancellationToken.None);
Console.WriteLine("File is now active.");

If processing fails, it throws GenerativeAIException.

Using a File in a Prompt

var request = new GenerateContentRequest();
request.AddRemoteFile(remoteFile);
request.AddText("Summarize this video.");

var response = await geminiModel.GenerateContentAsync(request);
Console.WriteLine(response.Text());

// Or pass the file URI and MIME type directly
var response2 = await geminiModel.GenerateContentAsync("Summarize this video.", remoteFile.Uri!, remoteFile.MimeType!);

Important Considerations

  • File size limits: Uploads are limited to FilesConstants.MaxUploadFileSize (2 GB). Larger files throw FileTooLargeException. Missing files throw FileNotFoundException.
  • MIME types: Unsupported MIME types throw NotSupportedException. Set the correct type when you upload from a stream.
  • Errors: API failures throw GenerativeAI.Exceptions.ApiException (ErrorCode, ErrorStatus, ErrorMessage).
  • Authentication: FileClient uses the credentials of its platform adapter. RegisterFilesAsync also needs an OAuth token. See Authentication.
  • Cancellation: Every method accepts a CancellationToken.

Related Pages

API Reference

Clone this wiki locally