PhxMediaLibrary.Plug.MediaDownload (PhxMediaLibrary v0.6.1)

Copy Markdown View Source

A Plug that serves local-disk media files with optional Content-Disposition and HMAC-signed URL verification.

Quick Start

Mount the plug in your Phoenix router at the same path you configured as download_base_url in the disk config:

# router.ex
forward "/media", PhxMediaLibrary.Plug.MediaDownload, disk: :local

# config.exs
config :phx_media_library,
  disks: [
    local: [
      adapter: PhxMediaLibrary.Storage.Disk,
      root: "priv/static/uploads",
      base_url: "/uploads",
      download_base_url: "/media",
      secret_key_base: "long-random-secret-at-least-32-bytes"
    ]
  ]

Generating Download / Signed URLs

Use the top-level helpers in PhxMediaLibrary:

# Content-Disposition download link (no signing required for public media)
href = PhxMediaLibrary.download_url(media)

# HMAC-signed URL (expires in 1 hour by default)
href = PhxMediaLibrary.signed_url(media)

# Signed *and* downloadable
href = PhxMediaLibrary.signed_url(media, nil, download: true, expires_in: 300)

URL Formats

Unsigned download (Content-Disposition only):

GET /media/images/1/uuid/photo.jpg?dl=1

Signed (no Content-Disposition):

GET /media/images/1/uuid/photo.jpg?sign=<token>&exp=<unix_ts>

Signed download:

GET /media/images/1/uuid/photo.jpg?sign=<token>&exp=<unix_ts>&dl=1

When a sign parameter is present the plug always verifies the token before serving the file. If the token is missing but the URL was generated with signed: true, verification fails with 403 Forbidden.

Plug Options

  • :disk — (required) the disk name atom (e.g. :local) to look up in the PhxMediaLibrary disk config. The disk must use PhxMediaLibrary.Storage.Disk as its adapter.

  • :require_signed — when true, every request must carry a valid sign + exp pair. Unsigned requests return 403 Forbidden. Defaults to false, which allows unsigned requests (no token required for plain download links).

Security Notes

  • Without :require_signed, any file under the configured :root directory can be downloaded via this plug. Use Phoenix's existing auth pipeline (:require_authenticated_user, etc.) to restrict access.
  • The HMAC secret (secret_key_base) should be at least 32 bytes of cryptographically random data. Do not reuse your Phoenix secret_key_base for this purpose in production.