Documentation Index
Fetch the complete documentation index at: https://mintlify.com/phoenixframework/phoenix_live_view/llms.txt
Use this file to discover all available pages before exploring further.
The struct representing an upload configuration.
Overview
The Phoenix.LiveView.UploadConfig module defines the configuration structure for file uploads in LiveView. It is created by allow_upload/3 and manages upload entries, validation, and processing.
Type Definition
@type t :: %Phoenix.LiveView.UploadConfig{
name: atom() | String.t(),
cid: :unregistered | nil | integer(),
client_key: String.t(),
max_entries: pos_integer(),
max_file_size: pos_integer(),
entries: list(),
entry_refs_to_pids: %{String.t() => pid() | :unregistered | :done},
entry_refs_to_metas: %{String.t() => map()},
accept: list() | :any,
acceptable_types: MapSet.t(),
acceptable_exts: MapSet.t(),
external: function() | false,
allowed?: boolean(),
errors: list(),
ref: String.t(),
auto_upload?: boolean(),
writer: function(),
progress_event: function() | nil
}
Struct Fields
The upload name provided to allow_upload/3
Unique reference for this upload configuration
List of upload entries (files)
Maximum number of files allowed. Default: 1
Maximum file size in bytes. Default: 8,000,000 (8MB)
Size of chunks for upload streaming. Default: 64,000 bytes
Timeout for chunk uploads in milliseconds. Default: 10,000ms
List of accepted file types or :any. Examples: [".jpg", ".png", "image/*"]
Set of acceptable MIME types
Set of acceptable file extensions
External upload function for third-party storage, or false for local uploads
Whether the upload is currently allowed
List of validation errors as {ref, error} tuples
Whether files should be uploaded automatically. Default: false
Optional callback for upload progress updates
Function that returns the writer module and options for handling uploads
Error Types
Upload validation can produce the following errors:
File exceeds max_file_size
Number of files exceeds max_entries
File type not in the accept list
Error during external upload
Default Values
@default_max_entries 1
@default_max_file_size 8_000_000 # 8 MB
@default_chunk_size 64_000 # 64 KB
@default_chunk_timeout 10_000 # 10 seconds
Usage
The upload config is created with allow_upload/3:
def mount(_params, _session, socket) do
socket =
socket
|> allow_upload(:avatar,
accept: ~w(.jpg .jpeg .png),
max_entries: 1,
max_file_size: 5_000_000
)
{:ok, socket}
end
Access the config in your assigns:
def render(assigns) do
~H"""
<%= for entry <- @uploads.avatar.entries do %>
<div>
<%= entry.client_name %> - <%= entry.progress %>%
</div>
<% end %>
<%= for err <- @uploads.avatar.errors do %>
<div class="error"><%= error_to_string(err) %></div>
<% end %>
"""
end
The :accept option supports:
File Extensions
Must start with a period and have a known MIME type:
accept: ~w(.jpg .jpeg .png .gif)
MIME Types
accept: ["image/jpeg", "image/png"]
MIME Type Wildcards
accept: ["image/*", "video/*", "audio/*"]
Any File Type
External Uploads
For uploads to external storage (S3, GCS, etc.):
def mount(_params, _session, socket) do
socket =
socket
|> allow_upload(:avatar,
accept: ~w(.jpg .jpeg .png),
max_entries: 1,
external: &presign_upload/2
)
{:ok, socket}
end
defp presign_upload(entry, socket) do
{:ok, meta, socket} =
Phoenix.LiveView.Upload.external_upload_meta(entry, socket)
# Generate presigned URL for your storage service
presigned_url = MyApp.Storage.generate_presigned_url(entry, socket)
{:ok, %{uploader: "S3", url: presigned_url}, socket}
end
Custom Writer
Provide a custom writer for advanced upload handling:
def mount(_params, _session, socket) do
socket =
socket
|> allow_upload(:avatar,
accept: :any,
writer: fn _name, _entry, _socket ->
{MyApp.CustomUploadWriter, [bucket: "uploads"]}
end
)
{:ok, socket}
end
Progress Callback
Track upload progress with a custom callback:
def mount(_params, _session, socket) do
socket =
socket
|> allow_upload(:documents,
accept: ["application/pdf"],
progress: &handle_progress/3
)
{:ok, socket}
end
defp handle_progress(:documents, entry, socket) do
if entry.done? do
# Upload complete
{:noreply, put_flash(socket, :info, "Upload complete!")}
else
# Still uploading
{:noreply, socket}
end
end
Auto Upload
Enable automatic upload on file selection:
def mount(_params, _session, socket) do
socket =
socket
|> allow_upload(:avatar,
accept: ~w(.jpg .jpeg .png),
auto_upload: true
)
{:ok, socket}
end
Validation Example
def error_to_string(:too_large), do: "File is too large"
def error_to_string(:too_many_files), do: "You have selected too many files"
def error_to_string(:not_accepted), do: "File type not accepted"
def render(assigns) do
~H"""
<form phx-change="validate" phx-submit="save">
<.live_file_input upload={@uploads.avatar} />
<%= for entry <- @uploads.avatar.entries do %>
<div>
<progress value={entry.progress} max="100"><%= entry.progress %>%</progress>
<button type="button" phx-click="cancel-upload" phx-value-ref={entry.ref}>×</button>
</div>
<% end %>
<%= for {_ref, error} <- @uploads.avatar.errors do %>
<p class="error"><%= error_to_string(error) %></p>
<% end %>
<button type="submit">Upload</button>
</form>
"""
end
def handle_event("validate", _params, socket) do
{:noreply, socket}
end
def handle_event("cancel-upload", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :avatar, ref)}
end
def handle_event("save", _params, socket) do
uploaded_files =
consume_uploaded_entries(socket, :avatar, fn %{path: path}, entry ->
dest = Path.join("uploads", entry.client_name)
File.cp!(path, dest)
{:ok, ~p"/uploads/#{entry.client_name}"}
end)
{:noreply, socket |> put_flash(:info, "Files uploaded!")}
end