PhoenixKit.Storage.FileServer (phoenix_kit v1.6.16)

View Source

File serving logic with multi-location failover support.

Handles retrieving files from storage locations with automatic failover, CDN integration, and proper HTTP header management.

Features

  • Query file locations from database
  • Priority-based location ordering
  • Automatic failover to next location on failure
  • CDN redirect support
  • HTTP header generation for streaming
  • Range request support (HTTP 206) for video streaming

Examples

iex> {:ok, file_info} = PhoenixKit.Storage.FileServer.get_file_location(
...>   "018e3c4a-9f6b-7890",
...>   "thumbnail"
...> )
iex> file_info.path
"/path/018e3c4a-9f6b-7890-thumbnail.jpg"
iex> file_info.bucket.cdn_url
"https://cdn.example.com"

Summary

Functions

Get file location with priority-ordered failover list.

Generate HTTP headers for file serving.

Check if a file location is accessible (has a path).

Handle range request for partial file serving (video streaming).

Functions

get_file_location(file_id, instance_name)

Get file location with priority-ordered failover list.

Queries the database for all active locations of a file instance, ordered by bucket priority and location priority for automatic failover.

Arguments

  • file_id (binary) - File UUID v7
  • instance_name (binary) - Variant name (e.g., "thumbnail", "medium")

Returns

  • {:ok, file_info} - Contains file metadata and location options
  • {:error, :not_found} - File instance or locations not found
  • {:error, :no_active_locations} - No active storage locations available

Example Response

{:ok, %{
  instance: %FileInstance{...},
  locations: [
    %FileLocation{
      path: "/path/018e3c4a-thumbnail.jpg",
      bucket: %Bucket{
        name: "Local SSD",
        provider: "local",
        cdn_url: nil,
        priority: 1
      },
      priority: 0,
      status: "active"
    },
    %FileLocation{
      path: "/path/018e3c4a-thumbnail.jpg",
      bucket: %Bucket{
        name: "Backblaze B2",
        provider: "b2",
        cdn_url: "https://cdn.example.com",
        priority: 2
      },
      priority: 0,
      status: "active"
    }
  ]
}}

http_headers(file_instance, options \\ [])

Generate HTTP headers for file serving.

Creates proper response headers including Content-Type, Content-Length, Cache-Control, and ETag for file streaming.

Arguments

  • file_instance (FileInstance) - File instance record with mime_type and size
  • options (keyword) - Options for header generation
    • :cache_control - Cache-Control header (default: "max-age=31536000, public, immutable")
    • :etag - Include ETag header (default: true)

Returns

Keyword list of HTTP headers.

Example

iex> headers = PhoenixKit.Storage.FileServer.http_headers(file_instance)
iex> headers[:content_type]
"image/jpeg"
iex> headers[:cache_control]
"max-age=31536000, public, immutable"

location_accessible?(arg1)

Check if a file location is accessible (has a path).

Verifies that a file location record contains a valid storage path.

Arguments

  • location (FileLocation) - File location record with preloaded bucket

Returns

Boolean indicating if location has a path.

parse_range_header(range_header, file_size)

Handle range request for partial file serving (video streaming).

Parses Range header and returns start/end positions for 206 Partial Content response.

Arguments

  • range_header (binary) - Range header value (e.g., "bytes=0-1023")
  • file_size (integer) - Total file size in bytes

Returns

  • {:ok, start, end, headers} - Valid range with response headers
  • {:error, :invalid_range} - Malformed range header
  • {:error, :range_out_of_bounds} - Range exceeds file size

Example

iex> PhoenixKit.Storage.FileServer.parse_range_header(
...>   "bytes=0-1023",
...>   5000
...> )
{:ok, 0, 1023, [content_range: "bytes 0-1023/5000"]}

iex> PhoenixKit.Storage.FileServer.parse_range_header(
...>   "bytes=1000-",
...>   5000
...> )
{:ok, 1000, 4999, [content_range: "bytes 1000-4999/5000"]}