File upload
Introduction
The file upload field is based on Filepond.
use Filament\Forms\Components\FileUpload;
FileUpload::make('attachment')

TIP
Filament also supports spatie/laravel-medialibrary. See our plugin documentation for more information.
NOTE
By default, FileUpload accepts any string path within the configured disk — the field value is a client-controlled string and a tampered request can submit any other file on the same disk. If your disk holds files for more than one user, tenant, or record, either call ->preventFilePathTampering() on the field (or apply it globally with FileUpload::configureUsing()), or isolate uploads at the disk or directory level so the field can only ever address files belonging to the current owner.
Configuring the storage disk and directory
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.
TIP
To correctly preview images and other files, FilePond requires files to be served from the same domain as the app, or the appropriate CORS headers need to be present. Ensure that the APP_URL environment variable is correct, or modify the filesystem driver to set the correct URL. If you're hosting files on a separate domain like S3, ensure that CORS headers are set up.
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')
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.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
NOTE
The default visibility is decided by a literal string match against the disk name: a disk literally named public is treated as publicly visible, and any other disk name defaults to private. A custom disk that happens to be named public will therefore be treated as public even if its underlying configuration is private, and a custom publicly-visible disk under a different name will default to private. To avoid confusion, either give custom disks unambiguous names or set visibility() explicitly on each field.
NOTE
It is the responsibility of the developer to delete these files from the disk if they are removed, as Filament is unaware if they are depended on elsewhere. One way to do this automatically is observing a model event.
Uploading multiple files
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())
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.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
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 array<string, string>
*/
protected function casts(): array
{
return [
'attachments' => 'array',
];
}
// ...
}
Controlling the maximum parallel uploads
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.
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.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Controlling file names
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.
Security implications of controlling file names
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.
Preserving original file names
NOTE
Before using this feature, please ensure that you have read the security implications.
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())
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.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Generating custom file names
NOTE
Before using this feature, please ensure that you have read the security implications.
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-'),
)
You can inject various utilities into the function passed to getUploadedFileNameForStorageUsing() as parameters.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| File | Livewire\Features\SupportFileUploads\TemporaryUploadedFile | $file | The temporary file object being uploaded. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
Storing original file names independently
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.
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.
Learn more about utility injection.| Utility | Type | Parameter | Description |
|---|---|---|---|
| Field | Filament\Forms\Components\Field | $component | The current field component instance. |
| Get function | Filament\Schemas\Components\Utilities\Get | $get | A function for retrieving values from the current form data. Validation is not run. |
| Livewire | Livewire\Component | $livewire | The Livewire component instance. |
| Eloquent model FQN | ?string<Illuminate\Database\Eloquent\Model> | $model | The Eloquent model FQN for the current schema. |
| Operation | string | $operation | The current operation being performed by the schema. Usually <code>create</code>, <code>edit</code>, or <code>view</code>. |
| Raw state | mixed | $rawState | The current value of the field, before state casts were applied. Validation is not run. |
| Eloquent record | ?Illuminate\Database\Eloquent\Model | $record | The Eloquent record for the current schema. |
| State | mixed | $state | The current value of the field. Validation is not run. |
