PhoenixKitWeb.FileController (phoenix_kit v1.7.113)

Copy Markdown View Source

File serving controller with signed URL support.

Handles secure file retrieval with token-based authentication and cache headers.

Summary

Functions

Get file information without serving the file.

Serve the DZI manifest for an image, generating it lazily if it doesn't exist yet.

Serve a single DZI tile, generating it lazily if it doesn't exist yet.

Serve a file variant by ID with signed URL token.

Functions

info(conn, map)

Get file information without serving the file.

Request

GET /api/files/:file_uuid/info

Response

Success (200):

{
  "file_uuid": "uuid",
  "original_filename": "photo.jpg",
  "mime_type": "image/jpeg",
  "file_type": "image",
  "size": 1234567,
  "status": "active",
  "variants": [
    {
      "variant_name": "original",
      "mime_type": "image/jpeg",
      "size": 1234567,
      "width": 1920,
      "height": 1080,
      "url": "/file/uuid/original/token"
    }
  ]
}

serve_manifest(conn, map)

Serve the DZI manifest for an image, generating it lazily if it doesn't exist yet.

Request

GET /tiles/:token/:dzi_filename

where dzi_filename is "<file_uuid>.dzi" and token is the signed per-file token from URLSigner.generate_token(file_uuid, "dzi"). Returns the XML manifest describing the image's dimensions and tile config — Tessera's generate_manifest/3 produces it on first request, subsequent requests serve from storage.

The token gates BOTH manifest and tile generation: without it, the endpoint is a 404. The MediaBrowser emits manifest URLs only when storage_tile_generation_enabled is on, so unauthenticated callers can't trigger lazy ImageMagick work by guessing UUIDs.

serve_tile(conn, map)

Serve a single DZI tile, generating it lazily if it doesn't exist yet.

Request

GET /tiles/:token/:files_segment/:level/:tile_filename

where token is the signed per-file token (same one used by serve_manifest/2), files_segment is "<file_uuid>_files", level is the integer zoom level, and tile_filename is "<col>_<row>.<ext>". This matches the layout Tessera writes to storage and the URL convention OpenSeadragon derives from a DZI manifest's base URL (token in the path survives that derivation; query-string tokens don't).

show(conn, map)

Serve a file variant by ID with signed URL token.

Request

GET /file/:file_uuid/:variant/:token

Parameters

  • file_uuid: UUID of the file
  • variant: Variant name (e.g., "original", "thumbnail", "medium")
  • token: Signed token for authentication

Response

Success (200):

  • File streamed to client with appropriate headers:
    • Cache-Control: public, max-age=31536000, immutable (1 year)
    • ETag: "md5-hash"
    • Content-Type: <mime-type>
    • Content-Disposition: inline; filename="..."

Not Modified (304):

  • Returned when request includes If-None-Match matching the file ETag

Error (401):

"Invalid or expired token"

Error (404):

"File or variant not found"