Skip to main content
FlexFileUpload ← Back to Table of Contents

Summary

Styled Filament file upload with security defaults, MIME presets, upload summaries, optional metadata sidecars, image optimization hooks, scoped per-user directories, and opt-in webcam capture / URL import tabs (v2.6.1).
FlexFileUploadBjanczak\FilamentFlexFields\Filament\Forms\Components\FlexFileUpload
FlexImageUploadBjanczak\FilamentFlexFields\Filament\Forms\Components\FlexImageUpload (extends FlexFileUpload, imagesOnly() preset)
State typestring|array|null — stored path(s) on disk
FieldTypefileFlexFileUpload, imageFlexImageUpload
ExtendsFilament\Forms\Components\FileUpload

Basic usage

Avatar (image)

use Bjanczak\FilamentFlexFields\Filament\Forms\Components\FlexImageUpload;

FlexImageUpload::make('avatar')
    ->label('Profile photo')
    ->withRecommendedDefaults()
    ->avatar()
    ->imageEditor()
    ->circleCropper()
    ->disk('public')
    ->directory('avatars')
    ->maxFiles(1)
    ->optimizeImages()
    ->maxImageWidth(512)
    ->maxImageHeight(512);

Single document

use Bjanczak\FilamentFlexFields\Filament\Forms\Components\FlexFileUpload;

FlexFileUpload::make('contract')
    ->label('Contract PDF')
    ->withRecommendedDefaults()
    ->documentsOnly()
    ->disk('local')
    ->directory('contracts')
    ->maxFiles(1)
    ->showFileIcon()
    ->uploadSummary()
    ->requireReplaceConfirmation();

Multiple files with total size guard

FlexFileUpload::make('attachments')
    ->withRecommendedDefaults()
    ->multiple()
    ->maxFiles(5)
    ->maxTotalSizeKb(10240)
    ->remainingSlotsLabel()
    ->uploadSummary()
    ->disk('local')
    ->directory('inquiries/attachments');

Metadata sidecar

Stores original filename, MIME, size, and image dimensions in a sibling state path:
FlexFileUpload::make('scan')
    ->withRecommendedDefaults()
    ->storeMetadataIn('scan_meta')
    ->disk('local')
    ->directory('scans');
// $data['scan_meta'] => ['original_name' => '...', 'mime' => '...', 'size' => ..., 'width' => ...]

Webcam & URL import

You can extend the default upload dropzone with additional input methods. The following example adds both a camera capture tab and a remote URL import tab:
FlexImageUpload::make('vehicle_photo')
    ->label('Vehicle Photo')
    ->withRecommendedDefaults()
    ->imagesOnly()
    ->allowWebcamUpload() // Enables the native device camera tab
    ->allowUrlUpload()    // Enables the remote URL download tab
    ->optimizeImages()
    ->maxImageWidth(1920)
    ->maxImageHeight(1080)
    ->disk('public')
    ->directory('vehicle-photos');

Configuration API

withRecommendedDefaults() / applyRecommendedSecurityDefaults()

Applies recommended security and UX defaults: createFormStrategy(), deleteFileOnRemove(), deleteReplacedFiles(), maxSize(5120) (5 MB), downloadable(), openable(), and focusOutline().
FlexFileUpload::make('attachment')
    ->withRecommendedDefaults();

documentsOnly()

Sets the accepted file types to typical document formats (PDF, Word, Excel, PowerPoint, Text, etc.).
FlexFileUpload::make('resume')
    ->documentsOnly();

imagesOnly()

Sets the accepted file types to image formats (JPEG, PNG, GIF, WebP, SVG, etc.).
FlexImageUpload::make('photo')
    ->imagesOnly();

spreadsheetsOnly()

Sets the accepted file types to spreadsheets (CSV, XLS, XLSX).
FlexFileUpload::make('report')
    ->spreadsheetsOnly();

allowedExtensions(array $extensions)

Restricts uploads to a custom array of file extensions.
FlexFileUpload::make('scan')
    ->allowedExtensions(['pdf', 'jpg', 'png']);

rejectExecutableFiles(bool|Closure $condition = true)

Blocks dangerous executable extensions (such as .php, .sh, .bat, etc.) and raises a validation error.
FlexFileUpload::make('attachment')
    ->rejectExecutableFiles();

scopedDirectory(string|Closure $prefix = 'uploads')

Configures dynamic per-user scoped subdirectories: {prefix}/{user_id}/....
FlexFileUpload::make('document')
    ->scopedDirectory('user-files');

allowWebcamUpload(bool|Closure $condition = true)

Adds a new “Camera” tab to the upload component, allowing users to directly capture photos using their device’s native camera. It supports dynamic front/back camera toggling (environment vs user facing), torch/flash control (if supported by hardware), and gives the user a chance to review/retake the photo before injecting it into the queue. Note: Since it uses the navigator.mediaDevices.getUserMedia browser API, this feature requires a secure context (HTTPS) to function correctly. It perfectly integrates with imagesOnly() and Filament’s optimizeImages() configurations.
FlexImageUpload::make('inspection_photo')
    ->label('Vehicle Damage Photo')
    ->imagesOnly()
    ->multiple()
    ->maxFiles(3)
    ->allowWebcamUpload() // Enables the camera tab
    ->optimizeImages()
    ->maxImageWidth(1920)
    ->maxImageHeight(1080);

allowUrlUpload(bool|Closure $condition = true)

Adds a new “URL” tab to the upload component, allowing users to paste a direct link to a file. The file is fetched server-side, validated against SSRF rules (localhost, private IPs, and metadata hostnames are rejected), staged as a temporary preview, then injected into the FilePond queue as a native File. Nothing is written to the field disk until form save.
FlexFileUpload::make('attachment')
    ->label('Import Asset')
    ->withRecommendedDefaults()
    ->allowUrlUpload() // Enables the remote URL import tab
    ->disk('public')
    ->directory('imported-assets');
Security: URL import is disabled unless you call allowUrlUpload(). Unsafe URLs are blocked before any server fetch runs.

createFormStrategy(bool|Closure $condition = true)

Prevents file path tampering by deferring disk storage until form submission.
FlexFileUpload::make('file')
    ->createFormStrategy();

storeMetadataIn(string|Closure $statePath)

Saves uploaded file metadata (original filename, MIME type, file size, image dimensions) to a separate database column or state path.
FlexFileUpload::make('document')
    ->storeMetadataIn('document_metadata');

maxTotalSizeKb(int|Closure $kilobytes)

Sets a maximum total file size limit in kilobytes across all uploaded files (useful for multiple file uploads).
FlexFileUpload::make('attachments')
    ->multiple()
    ->maxTotalSizeKb(10240); // 10 MB total limit

remainingSlotsLabel(bool|Closure $condition = true)

Displays a remaining slots label (e.g. “2 slots remaining”) when maxFiles is set.
FlexFileUpload::make('gallery')
    ->multiple()
    ->maxFiles(5)
    ->remainingSlotsLabel();

minImageDimensions(int $width, int $height)

Validates that uploaded images meet minimum width and height constraints.
FlexImageUpload::make('banner')
    ->minImageDimensions(1200, 400);

maxImageDimensions(int $width, int $height)

Validates that uploaded images do not exceed maximum width and height constraints.
FlexImageUpload::make('thumbnail')
    ->maxImageDimensions(800, 600);

deleteFileOnRemove(bool|Closure $condition = true)

Deletes files from storage when they are removed from the form UI.
FlexFileUpload::make('document')
    ->deleteFileOnRemove();

deleteReplacedFiles(bool|Closure $condition = true)

Deletes old files from storage when they are replaced by new uploads.
FlexFileUpload::make('document')
    ->deleteReplacedFiles();

pruneOrphanedOnSave(bool|Closure $condition = true)

Removes old, unreferenced files from the upload directory when saving the model.
Warning Do not use this with a shared static directory() (e.g., ->directory('gallery')). This method deletes ALL files in the specified directory that do not belong to the current record. Using it on a shared directory will cause you to lose files from other records! You must use this method in combination with ->scopedDirectory() or a closure that provides a unique directory per record.
FlexFileUpload::make('gallery')
    ->scopedDirectory('galleries')
    ->pruneOrphanedOnSave();

uploadSummary(bool|Closure $condition = true)

Displays a summary block below the file list containing count and total file size.
FlexFileUpload::make('attachments')
    ->multiple()
    ->uploadSummary();

emptyStateHint(string|Closure $hint)

Sets a custom hint text displayed inside the dropzone when it is empty.
FlexFileUpload::make('avatar')
    ->emptyStateHint('Drag your avatar here...');

dropzoneLabel(string|Closure $label)

Overrides the main dropzone label text.
FlexFileUpload::make('invoice')
    ->dropzoneLabel('Upload invoice (PDF)');

requireReplaceConfirmation(bool|Closure $condition = true)

Asks the user for confirmation before replacing an already uploaded file.
FlexFileUpload::make('document')
    ->requireReplaceConfirmation();

compactList(bool|Closure $condition = true)

Renders a denser, more compact layout for the uploaded files list.
FlexFileUpload::make('attachments')
    ->multiple()
    ->compactList();

showFileIcon(bool|Closure $condition = true)

Displays a descriptive file type icon in the uploaded files list.
FlexFileUpload::make('attachments')
    ->multiple()
    ->showFileIcon();

variant(string|Closure $variant)

Sets the visual design variant (primary, secondary, or flat).
FlexFileUpload::make('document')
    ->variant('flat');

optimizeImages(bool|Closure $condition = true)

Resizes and compresses images to optimize page weight (requires GD or Imagick).
FlexImageUpload::make('photo')
    ->optimizeImages();

optimizeImagesToWebp(bool|Closure $condition = false)

Converts optimized image files to the WebP format.
FlexImageUpload::make('photo')
    ->optimizeImagesToWebp();

maxImageWidth(int|Closure $width) / maxImageHeight(int|Closure $height)

Sets maximum image width and height boundaries for client-side resizing.
FlexImageUpload::make('photo')
    ->maxImageWidth(1920)
    ->maxImageHeight(1080);

stripExif(bool|Closure $condition = true)

Strips EXIF metadata from uploaded images on save.
FlexImageUpload::make('photo')
    ->stripExif();

Inherited Filament FileUpload API

disk(), directory(), visibility(), multiple(), maxFiles(), minFiles(), maxSize(), acceptedFileTypes(), imageEditor(), avatar(), downloadable(), openable(), previewable(), deletable(), standard validation — all work unchanged.

FlexField schema config

Config keyMaps to
diskdisk()
directorydirectory()
visibilityvisibility()
multiplemultiple()
max_size_kb / max_sizemaxSize()
max_files / min_filesmaxFiles() / minFiles()
max_total_size_kbmaxTotalSizeKb()
accepted_typesacceptedFileTypes()
documents_onlydocumentsOnly()
images_onlyimagesOnly()
variantvariant()
sizesize()
store_metadata_instoreMetadataIn()
scoped_directoryscopedDirectory()
optimize_imagesoptimizeImages()
max_image_width / max_image_heightmaxImageWidth() / maxImageHeight()
allow_webcam_uploadallowWebcamUpload()
allow_url_uploadallowUrlUpload()

Security

ConcernBehaviour
Executable uploadsrejectExecutableFiles() blocks dangerous extensions (.php, .sh, …).
URL import SSRFServer-side fetch rejects localhost, loopback, private/link-local IPs, .local / .internal hostnames, and cloud metadata endpoints before download.
Webcam captureRequires HTTPS (getUserMedia secure context). Not offered for documentsOnly() uploads.
Deferred disk writescreateFormStrategy() (included in withRecommendedDefaults()) prevents path tampering until form save.

CSS classes

ClassMeaning
fff-flex-file-uploadRoot wrapper
fff-flex-file-upload--{primary|secondary|flat}Variant
fff-flex-file-upload--{sm|md|lg}Size

Implementation notes

  • Requires Livewire temporary uploads; configure FILESYSTEM_DISK and disk credentials.
  • Webcam capture requires HTTPS. URL import rejects unsafe remote URLs before server fetch.
  • Playground examples under File upload in Flex Fields Playground (File / Camera / URL tabs).
  • For Spatie Media Library integration, see package FlexSpatieMediaLibraryFileUpload (if installed in app).