File upload
The file upload field stores uploaded files on a filesystem disk and submits their paths. It supports
single or multiple files, image-only mode, size and count limits, and direct-to-storage signed uploads.
Create one with FileUpload::make().
FileUpload::make('avatar', 'Avatar') ->image() ->maxSize(2048)- accept:"image/*"
- columnWidth:"md"
- conditions:null
- dependsOnAny:false
- dependsOnKeys:null
- disabled:false
- editablePrefill:false
- files:null
- helperText:null
- hidden:false
- image:true
- label:"Avatar"
- maxFiles:null
- maxSize:2048
- multiple:false
- name:"avatar"
- prefillRefreshOn:null
- prefillResetOn:null
- readOnly:false
- required:false
- signed:false
- tooltip:null
- value:null
->disk() chooses the filesystem disk the field reads and writes. Without it the field uses the
lattice.files.disk config value (defaulting to public).
FileUpload::make('document')->disk('s3');Images
Section titled “Images”->image() restricts the picker to images and renders an image-aware preview. It also defaults the
accepted types to image/* unless you set them explicitly.
FileUpload::make('avatar')->image();Accepted types and size
Section titled “Accepted types and size”->acceptedFileTypes() takes a list of MIME types or extensions for the file picker’s accept
attribute. ->maxSize() caps each file’s size in kilobytes.
FileUpload::make('attachment') ->acceptedFileTypes(['application/pdf', 'image/png']) ->maxSize(5120);Multiple files
Section titled “Multiple files”->multiple() lets the field accept more than one file; it then submits an array of paths. ->maxFiles()
caps how many the form accepts.
FileUpload::make('gallery', 'Gallery') ->image() ->multiple() ->maxFiles(8);Signed (direct-to-storage) uploads
Section titled “Signed (direct-to-storage) uploads”By default files are uploaded through your form endpoint. ->signedUpload() switches to direct
uploads: the client asks the form endpoint for a short-lived signed URL, uploads straight to the
disk (for example S3), and submits the resulting object key. This keeps large files off your PHP
process. The disk must support temporary upload URLs.
FileUpload::make('document') ->disk('s3') ->signedUpload();Reading the value in handle()
Section titled “Reading the value in handle()”A submitted file arrives as an UploadedFile (or an array of them for ->multiple()); store it
however you like:
public function handle(Request $request): Response{ $data = $this->validate($request);
if (($data['avatar'] ?? null) instanceof UploadedFile) { $data['avatar'] = $data['avatar']->store('avatars', 'public'); }
// persist $data['avatar'] ...}Finalizing a signed upload
Section titled “Finalizing a signed upload”A signed upload arrives as a temporary object key under lattice.files.temp_prefix, not the final
path — temporary objects are cleaned up, so you must promote the key out of the temp prefix before
persisting it. Call finalizeSignedUploads() on the same field, passing the submitted keys and a
closure that returns each file’s destination path. It moves the object and returns the finalized
disk, path, name, mime_type, and size for each file:
$finalized = FileUpload::make('document')->disk('s3')->signedUpload() ->finalizeSignedUploads( (array) $data['document'], fn (string $key, array $meta): string => "documents/{$request->user()->id}.{$meta['extension']}", );
foreach ($finalized as $upload) { // $upload['disk'], $upload['path'], $upload['name'], $upload['mime_type'], $upload['size']}Removing existing files
Section titled “Removing existing files”When a form is bound to a record, stored paths render as existing files the user can remove. Each
existing file carries a sealed token, and the client posts the tokens of removed files under
{name}__removed[]. Resolve them server-side with the static FileUpload::removed() helper, which
unseals each token (skipping any forged, expired, or mismatched one) and returns the trusted disk
paths to delete:
foreach (FileUpload::removed($request, 'avatar') as $path) { Storage::disk('public')->delete($path);}Common options
Section titled “Common options”FileUpload shares label, required, disabled, read-only, and visibility options with every field — see
Fields. For validation and conditional behavior, see
Validation and Conditional fields.