# `Gemini.APIs.Files`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L1)

Files API for uploading, managing, and using files with Gemini models.

The Files API allows you to upload files (images, videos, audio, documents)
that can be referenced in content generation requests. This is useful for
multimodal interactions where you want to include media files.

## Important Notes

- **Gemini API Only**: File operations are only supported with the Gemini Developer API,
  not Vertex AI. Using file operations with Vertex AI will return an error.
- **File Expiration**: Uploaded files expire after 48 hours
- **Project Storage Limit**: Gemini caps total uploaded file storage at 20 GB per project
- **Size Limits**: Maximum file size is 2GB for most file types
- **Processing Time**: Video files may take time to process

## Quick Start

    # Upload an image
    {:ok, file} = Gemini.APIs.Files.upload("path/to/image.png", auth: :gemini)

    # Use the File struct directly in content generation
    {:ok, response} = Gemini.generate([file, "What's in this image?"])

    # Video files may need polling until they become active
    {:ok, video} = Gemini.APIs.Files.upload("path/to/video.mp4", auth: :gemini)
    {:ok, ready_video} = Gemini.APIs.Files.wait_for_processing(video.name, auth: :gemini)
    {:ok, video_response} = Gemini.generate([ready_video, "Describe this video clip"])

    # Clean up when done
    :ok = Gemini.APIs.Files.delete(file.name, auth: :gemini)
    :ok = Gemini.APIs.Files.delete(video.name, auth: :gemini)

## Resumable Uploads

This module uses the resumable upload protocol for file uploads:

    # Large file upload with progress tracking
    {:ok, file} = Gemini.APIs.Files.upload("path/to/video.mp4",
      on_progress: fn uploaded, total ->
        percent = Float.round(uploaded / total * 100, 1)
        IO.puts("Uploaded: #{percent}%")
      end
    )

## Supported MIME Types

- Images: `image/png`, `image/jpeg`, `image/gif`, `image/webp`
- Videos: `video/mp4`, `video/mpeg`, `video/mov`, `video/avi`, `video/webm`
- Audio: `audio/wav`, `audio/mp3`, `audio/aiff`, `audio/aac`, `audio/ogg`, `audio/flac`
- Documents: `application/pdf`, `text/plain`, `text/html`, `text/css`, `text/javascript`

# `file_opts`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L81)

```elixir
@type file_opts() :: [api_key: String.t(), auth: :gemini | :vertex_ai]
```

# `list_opts`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L74)

```elixir
@type list_opts() :: [
  page_size: pos_integer(),
  page_token: String.t(),
  api_key: String.t(),
  auth: :gemini | :vertex_ai
]
```

# `register_files_opts`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L725)

```elixir
@type register_files_opts() :: [
  credentials: map(),
  config: map(),
  api_key: String.t(),
  auth: :gemini | :vertex_ai
]
```

# `upload_opts`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L65)

```elixir
@type upload_opts() :: [
  name: String.t(),
  display_name: String.t(),
  mime_type: String.t(),
  on_progress: (integer(), integer() -&gt; any()),
  api_key: String.t(),
  auth: :gemini | :vertex_ai
]
```

# `delete`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L314)

```elixir
@spec delete(String.t(), file_opts()) :: :ok | {:error, term()}
```

Delete a file.

## Parameters

- `name` - File resource name (e.g., "files/abc123")
- `opts` - Options

## Examples

    :ok = Gemini.APIs.Files.delete("files/abc123", auth: :gemini)

# `download`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L382)

```elixir
@spec download(Gemini.Types.File.t() | String.t(), file_opts()) ::
  {:ok, binary()} | {:error, term()}
```

Download a generated file's content.

Only works for files with `source: :generated` (e.g., from video generation).
Uploaded files cannot be downloaded - you already have the source.

## Parameters

- `file` - File struct or file name
- `opts` - Options

## Examples

    {:ok, file} = Gemini.APIs.Files.get("files/generated-video-123")
    {:ok, video_data} = Gemini.APIs.Files.download(file)
    File.write!("output.mp4", video_data)

# `get`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L234)

```elixir
@spec get(String.t(), file_opts()) :: {:ok, Gemini.Types.File.t()} | {:error, term()}
```

Get file metadata by name.

## Parameters

- `name` - File resource name (e.g., "files/abc123")
- `opts` - Options

## Examples

    {:ok, file} = Gemini.APIs.Files.get("files/abc123", auth: :gemini)
    IO.puts("State: #{file.state}")
    IO.puts("MIME type: #{file.mime_type}")

# `list`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L271)

```elixir
@spec list(list_opts()) ::
  {:ok, Gemini.Types.ListFilesResponse.t()} | {:error, term()}
```

List all uploaded files.

## Parameters

- `opts` - List options

## Options

- `:page_size` - Number of files per page (Gemini supports up to 100)
- `:page_token` - Token from previous response for pagination
- `:api_key` - Per-request Gemini API key override
- `:auth` - Authentication strategy

## Examples

    # List first page
    {:ok, response} = Gemini.APIs.Files.list(auth: :gemini)
    Enum.each(response.files, fn file ->
      IO.puts("#{file.name}: #{file.mime_type}")
    end)

    # Paginate through all files
    {:ok, all_files} = Gemini.APIs.Files.list_all(auth: :gemini)

# `list_all`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L297)

```elixir
@spec list_all(list_opts()) :: {:ok, [Gemini.Types.File.t()]} | {:error, term()}
```

List all files across all pages.

Automatically handles pagination to retrieve all files.

## Parameters

- `opts` - List options (`:page_size` can be set, default 100)

## Examples

    {:ok, all_files} = Gemini.APIs.Files.list_all(auth: :gemini)
    IO.puts("Total files: #{length(all_files)}")

# `register_files`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L782)

```elixir
@spec register_files([String.t()], register_files_opts()) ::
  {:ok, Gemini.Types.RegisterFilesResponse.t()} | {:error, term()}
```

Registers GCS files with the Gemini file service.

This allows using Google Cloud Storage files directly with Gemini models
without uploading them first.

**Note:** This method is only supported in the Gemini Developer API,
not Vertex AI.

## Parameters

- `uris` - List of GCS URIs (e.g., `["gs://bucket/object"]`)
- `opts` - Options:
  - `:credentials` - Google Cloud credentials (required). Can be:
    - A map with `:token` key containing the access token
    - A Goth token struct
  - `:config` - Optional RegisterFilesConfig
  - `:api_key` - Per-request Gemini API key override
  - `:auth` - Authentication strategy (must be `:gemini`)

## Returns

- `{:ok, RegisterFilesResponse.t()}` - Successfully registered files
- `{:error, term()}` - Registration failed

## Example

    # Get credentials (using Goth or similar)
    {:ok, token} = Goth.fetch(MyApp.Goth)

    {:ok, response} = Gemini.APIs.Files.register_files(
      ["gs://my-bucket/file1.txt", "gs://my-bucket/file2.pdf"],
      credentials: %{token: token.token},
      auth: :gemini
    )

    # Use the registered files
    file = hd(response.files)
    Gemini.generate([file, "Summarize this document"])

## GCS URI Format

URIs must be in the format `gs://bucket/object`, for example:
- `gs://my-bucket/documents/report.pdf`
- `gs://my-bucket/images/photo.jpg`

The credentials must have read access to the GCS bucket.

# `upload`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L136)

```elixir
@spec upload(Path.t() | String.t(), upload_opts()) ::
  {:ok, Gemini.Types.File.t()} | {:error, term()}
```

Upload a file to be used with Gemini models.

## Parameters

- `file_path` - Path to the file to upload (string or Path)
- `opts` - Upload options

## Options

- `:name` - Custom file resource name (auto-generated if not provided)
- `:display_name` - Human-readable display name (max 512 characters)
- `:mime_type` - MIME type (auto-detected from extension if not provided)
- `:on_progress` - Callback function `fn(uploaded_bytes, total_bytes) -> any()` for progress updates
- `:api_key` - Per-request Gemini API key override
- `:auth` - Authentication strategy (must be `:gemini`)

## Returns

- `{:ok, File.t()}` - Successfully uploaded file with metadata
- `{:error, reason}` - Upload failed

## Examples

    # Simple upload
    {:ok, file} = Gemini.APIs.Files.upload("path/to/image.png", auth: :gemini)
    IO.puts("Uploaded: #{file.uri}")

    # With display name
    {:ok, file} = Gemini.APIs.Files.upload("document.pdf",
      display_name: "Important Document",
      auth: :gemini
    )

    # With progress tracking
    {:ok, file} = Gemini.APIs.Files.upload("large_video.mp4",
      on_progress: fn uploaded, total ->
        IO.puts("Progress: #{div(uploaded * 100, total)}%")
      end,
      auth: :gemini
    )

# `upload_data`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L193)

```elixir
@spec upload_data(binary(), upload_opts()) ::
  {:ok, Gemini.Types.File.t()} | {:error, term()}
```

Upload a file from binary data.

## Parameters

- `data` - Binary data to upload
- `opts` - Upload options (`:mime_type` is required)

## Examples

    image_data = File.read!("image.png")
    {:ok, file} = Gemini.APIs.Files.upload_data(image_data,
      mime_type: "image/png",
      display_name: "My Image",
      auth: :gemini
    )

# `wait_for_processing`
[🔗](https://github.com/nshkrdotcom/gemini_ex/blob/v0.11.0/lib/gemini/apis/files.ex#L353)

```elixir
@spec wait_for_processing(
  String.t(),
  keyword()
) :: {:ok, Gemini.Types.File.t()} | {:error, term()}
```

Wait for a file to finish processing.

Polls the file status until it reaches `:active` or `:failed` state.

## Parameters

- `name` - File resource name
- `opts` - Options

## Options

- `:poll_interval` - Milliseconds between status checks (default: 2000)
- `:timeout` - Maximum wait time in milliseconds (default: 300000 = 5 min)
- `:on_status` - Callback for status updates `fn(File.t()) -> any()`

## Examples

    {:ok, file} = Gemini.APIs.Files.upload("video.mp4", auth: :gemini)

    {:ok, ready_file} = Gemini.APIs.Files.wait_for_processing(file.name,
      poll_interval: 5000,
      on_status: fn f -> IO.puts("Status: #{f.state}") end,
      auth: :gemini
    )

---

*Consult [api-reference.md](api-reference.md) for complete listing*
