filament/forms
Filament Forms is a Laravel package for building powerful, reactive admin forms with a fluent, component-based API. Create fields, layouts, validation, conditional logic, and dynamic interactions quickly, with tight Livewire integration and great DX for panels and apps.
title: File upload
import Aside from "@components/Aside.astro" import AutoScreenshot from "@components/AutoScreenshot.astro" import UtilityInjection from "@components/UtilityInjection.astro"
The file upload field is based on Filepond.
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachment')
By default, files will be uploaded to the storage disk defined in the configuration file. You can also set the FILESYSTEM_DISK environment variable to change this.
To change the disk and directory for a specific field, and the visibility of files, use the disk(), directory() and visibility() methods. By default, files are uploaded with private visibility to your storage disk, unless the disk is set to public:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachment')
->disk('s3')
->directory('form-attachments')
->visibility('public')
<UtilityInjection set="formFields" version="5.x">As well as allowing static values, the disk(), directory() and visibility() methods accept functions to dynamically calculate them. You can inject various utilities into the functions as parameters. </UtilityInjection>
You may also upload multiple files. This stores URLs in JSON:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
Optionally, you may pass a boolean value to control if multiple files can be uploaded at once:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple(FeatureFlag::active())
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the multiple() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
If you're saving the file URLs using Eloquent, you should be sure to add an array cast to the model property:
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
/**
* [@return](https://github.com/return) array<string, string>
*/
protected function casts(): array
{
return [
'attachments' => 'array',
];
}
// ...
}
You can control the maximum number of parallel uploads using the maxParallelUploads() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
->maxParallelUploads(1)
This will limit the number of parallel uploads to 1. If unset, we'll use the default FilePond value which is 2.
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the maxParallelUploads() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
By default, a random file name will be generated for newly-uploaded files. This is to ensure that there are never any conflicts with existing files.
Before using the preserveFilenames() or getUploadedFileNameForStorageUsing() methods, please be aware of the security implications. If you allow users to upload files with their own file names, there are ways that they can exploit this to upload malicious files. This applies even if you use the acceptedFileTypes() method to restrict the types of files that can be uploaded, since it uses Laravel's mimetypes rule which does not validate the extension of the file, only its mime type, which could be manipulated.
This is specifically an issue with the getClientOriginalName() method on the TemporaryUploadedFile object, which the preserveFilenames() method uses. By default, Livewire generates a random file name for each file uploaded, and uses the mime type of the file to determine the file extension.
Using these methods with the local or public filesystem disks will make your app vulnerable to remote code execution if the attacker uploads a PHP file with a deceptive mime type. Using an S3 disk protects you from this specific attack vector, as S3 will not execute PHP files in the same way that your server might when serving files from local storage.
If you are using the local or public disk, you should consider using the storeFileNamesIn() method to store the original file names in a separate column in your database, and keep the randomly generated file names in the file system. This way, you can still display the original file names to users, while keeping the file system secure.
On top of this security issue, you should also be aware that allowing users to upload files with their own file names can lead to conflicts with existing files, and can make it difficult to manage your storage. Users could upload files with the same name and overwrite the other's content if you do not scope them to a specific directory, so these features should in all cases only be accessible to trusted users.
To preserve the original filenames of the uploaded files, use the preserveFilenames() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachment')
->preserveFilenames()
Optionally, you may pass a boolean value to control if the original file names should be preserved:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachment')
->preserveFilenames(FeatureFlag::active())
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the preserveFilenames() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
You may completely customize how file names are generated using the getUploadedFileNameForStorageUsing() method, and returning a string from the closure based on the $file that was uploaded:
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
FileUpload::make('attachment')
->getUploadedFileNameForStorageUsing(
fn (TemporaryUploadedFile $file): string => (string) str($file->getClientOriginalName())
->prepend('custom-prefix-'),
)
<UtilityInjection set="formFields" version="5.x" extras="File;;Livewire\Features\SupportFileUploads\TemporaryUploadedFile;;$file;;The temporary file object being uploaded.">You can inject various utilities into the function passed to getUploadedFileNameForStorageUsing() as parameters.</UtilityInjection>
You can keep the randomly generated file names, while still storing the original file name, using the storeFileNamesIn() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
->storeFileNamesIn('attachment_file_names')
attachment_file_names will now store the original file names of your uploaded files, so you can save them to the database when the form is submitted. If you're uploading multiple() files, make sure that you add an array cast to this Eloquent model property too.
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the storeFileNamesIn() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
You can enable avatar mode for your file upload field using the avatar() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('avatar')
->avatar()
This will only allow images to be uploaded, and when they are, it will display them in a compact circle layout that is perfect for avatars.
This feature pairs well with the circle cropper.
You can enable an image editor for your file upload field using the imageEditor() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor()
You can open the editor once you upload an image by clicking the pencil icon. You can also open the editor by clicking the pencil icon on an existing image, which will remove and re-upload it on save.
Optionally, you may pass a boolean value to control if the image editor is enabled:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor(FeatureFlag::active())
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the imageEditor() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
You can allow users to crop images to a set of specific aspect ratios using the imageEditorAspectRatioOptions() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor()
->imageEditorAspectRatioOptions([
'16:9',
'4:3',
'1:1',
])
You can also allow users to choose no aspect ratio, "free cropping", by passing null as an option:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor()
->imageEditorAspectRatioOptions([
null,
'16:9',
'4:3',
'1:1',
])
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the imageEditorAspectRatioOptions() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
You can change the mode of the image editor using the imageEditorMode() method, which accepts either 1, 2 or 3. These options are explained in the Cropper.js documentation:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor()
->imageEditorMode(2)
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the imageEditorMode() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
By default, the image editor will make the empty space around the image transparent. You can customize this using the imageEditorEmptyFillColor() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor()
->imageEditorEmptyFillColor('#000000')
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the imageEditorEmptyFillColor() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
You can change the size of the image editor's viewport using the imageEditorViewportWidth() and imageEditorViewportHeight() methods, which generate an aspect ratio to use across device sizes:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageEditor()
->imageEditorViewportWidth('1920')
->imageEditorViewportHeight('1080')
<UtilityInjection set="formFields" version="5.x">As well as allowing static values, the imageEditorViewportWidth() and imageEditorViewportHeight() methods also accept functions to dynamically calculate them. You can inject various utilities into the functions as parameters.</UtilityInjection>
You can allow users to crop images as a circle using the circleCropper() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->avatar()
->imageEditor()
->circleCropper()
This is perfectly accompanied by the avatar() method, which renders the images in a compact circle layout.
Optionally, you may pass a boolean value to control if the circle cropper is enabled:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->avatar()
->imageEditor()
->circleCropper(FeatureFlag::active())
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the circleCropper() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
If you need to ensure all uploaded images conform to a specific aspect ratio, you can combine the imageAspectRatio() validation method with automaticallyOpenImageEditorForAspectRatio(). This will automatically open a simplified image editor when a user uploads an image that doesn't match the required aspect ratio, allowing them to crop the image before it is saved:
use Filament\Forms\Components\FileUpload;
FileUpload::make('banner')
->image()
->imageAspectRatio('16:9')
->automaticallyOpenImageEditorForAspectRatio()
The editor that appears when cropping is required only shows the crop area and save/cancel buttons - it does not include the full editing controls (rotation, position inputs, etc.) that appear when using imageEditor(). This provides a streamlined experience focused on getting the correct aspect ratio.
If you want users to have access to the full image editor controls, you can enable both:
use Filament\Forms\Components\FileUpload;
FileUpload::make('banner')
->image()
->imageEditor()
->imageAspectRatio('16:9')
->automaticallyOpenImageEditorForAspectRatio()
With both enabled, the image editor will still open automatically when the aspect ratio doesn't match, but users will also see an edit button on each uploaded image and have access to all editing controls.
Optionally, you may pass a boolean value to control if the aspect ratio editor is enabled:
use Filament\Forms\Components\FileUpload;
FileUpload::make('banner')
->image()
->imageAspectRatio('16:9')
->automaticallyOpenImageEditorForAspectRatio(FeatureFlag::active())
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the automaticallyOpenImageEditorForAspectRatio() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
Filepond allows you to crop and resize images before they are uploaded, without the need for a separate editor. You can customize this behavior using the automaticallyResizeImagesToHeight() and automaticallyResizeImagesToWidth() methods. automaticallyResizeImagesMode() should be set for these methods to have an effect - either force, cover, or contain.
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->automaticallyCropImagesToAspectRatio('16:9')
->automaticallyResizeImagesMode('cover')
->automaticallyResizeImagesToWidth('1920')
->automaticallyResizeImagesToHeight('1080')
To enable automatic cropping with a specific aspect ratio, use the automaticallyCropImagesToAspectRatio() method. If you also have imageAspectRatio() set for validation and want the automatic crop to use the same ratio, you can call automaticallyCropImagesToAspectRatio() without any arguments:
use Filament\Forms\Components\FileUpload;
FileUpload::make('image')
->image()
->imageAspectRatio('16:9')
->automaticallyCropImagesToAspectRatio()
->automaticallyResizeImagesMode('cover')
->automaticallyResizeImagesToWidth('1920')
->automaticallyResizeImagesToHeight('1080')
<UtilityInjection set="formFields" version="5.x">As well as allowing static values, the automaticallyResizeImagesMode(), automaticallyCropImagesToAspectRatio(), automaticallyResizeImagesToHeight() and automaticallyResizeImagesToWidth() methods also accept functions to dynamically calculate them. You can inject various utilities into the functions as parameters.</UtilityInjection>
You may also alter the general appearance of the Filepond component. Available options for these methods are available on the Filepond website.
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachment')
->imagePreviewHeight('250')
->loadingIndicatorPosition('left')
->panelAspectRatio('2:1')
->panelLayout('integrated')
->removeUploadedFileButtonPosition('right')
->uploadButtonPosition('left')
->uploadProgressIndicatorPosition('left')
<UtilityInjection set="formFields" version="5.x">As well as allowing static values, these methods also accept functions to dynamically calculate them. You can inject various utilities into the functions as parameters.</UtilityInjection>
You can use the Filepond grid layout by setting the panelLayout():
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
->panelLayout('grid')
<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the panelLayout() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>
You can also allow users to re-order uploaded files using the reorderable() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
->reorderable()
When using this method, FilePond may add newly-uploaded files to the beginning of the list, instead of the end. To fix this, use the appendFiles() method:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
->reorderable()
->appendFiles()
Optionally, the reorderable() and appendFiles() methods accept a boolean value to control if the files can be reordered and if new files should be appended to the end of the list:
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachments')
->multiple()
->reorderable(FeatureFlag::active())
->appendFiles(Fea.....
How can I help you explore Laravel packages today?