Powerful suite of Blade components for TALL Stack apps.

Form Upload

>= v1.13

Form upload component.

Files can be uploaded through selection or drag-and-drop. Also, when sending a png, jpg, jpeg or gif file, a preview is offered when clicking on the file image. To disable the preview, simply pass the :preview="false" parameter to the component.

All files uploaded as part of tests on this page are deleted each hour.

Click here to upload

<x-upload />
We need to analyze your screenshot

Click here to upload

Drag and drop your screenshot here

<x-upload label="Screenshot"
hint="We need to analyze your screenshot"
tip="Drag and drop your screenshot here" />

Click here to upload

<!-- The Livewire component should have the "deleteUpload" method -->
 
<x-upload delete />
 
<!-- Or you can specify a different method name -->
 
<x-upload delete delete-method="deleting" />

You can use this algorithm to be the base of the method of deleting temporary files.

use Illuminate\Support\Arr;
use Illuminate\Http\UploadedFile;
 
public function deleteUpload(array $content): void
{
/*
the $content contains:
[
'temporary_name',
'real_name',
'extension',
'size',
'path',
'url',
]
*/
 
if (! $this->photo) {
return;
}
 
$files = Arr::wrap($this->photo);
 
/** @var UploadedFile $file */
$file = collect($files)->filter(fn (UploadedFile $item) => $item->getFilename() === $content['temporary_name'])->first();
 
// 1. Here we delete the file. Even if we have a error here, we simply
// ignore it because as long as the file is not persisted, it is
// temporary and will be deleted at some point if there is a failure here.
rescue(fn () => $file->delete(), report: false);
 
$collect = collect($files)->filter(fn (UploadedFile $item) => $item->getFilename() !== $content['temporary_name']);
 
// 2. We guarantee restore of remaining files regardless of upload
// type, whether you are dealing with multiple or single uploads
$this->photo = is_array($this->photo) ? $collect->toArray() : $collect->first();
}

Click here to upload

<!-- The Livewire property must be an array -->
 
<x-upload multiple />

If you have ever uploaded multiple files, you may have already encountered this issue: after selecting some files, if new files are selected they replace the selected ones with the new selected files, instead of merging them. To solve this problem and allow your user to select multiple files, in batches, you can use an algorithm like this:

use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Http\UploadedFile;
 
class MyComponent extends Component
{
use WithFileUploads;
 
// For multiple files the property must be an array
public $photos = [];
 
// 1. We create a property that will temporarily store the uploaded files
public $backup = [];
 
public function updatingPhotos(): void
{
// 2. We store the uploaded files in the temporary property
$this->backup = $this->photos;
}
 
public function updatedPhotos(): void
{
if (!$this->photos) {
return;
}
 
// 3. We merge the newly uploaded files with the saved ones
$file = Arr::flatten(array_merge($this->backup, [$this->photos]));
 
// 4. We finishing by removing the duplicates
$this->photos = collect($file)->unique(fn (UploadedFile $item) => $item->getClientOriginalName())->toArray();
}
 
// ...
}

The only thing to pay attention to with this approach is that real-time validations may not work correctly to display validation errors linked to the correct files, so if you want to use this strategy we suggest that you use a single validation with properties bind with wire:model . Also, remember to update the methods with the name of the property you are using to upload files, following Livewire lifecycle hooks convention:

// Supposing you want to use $files instead of $photos:
 
public $photos = [];
public $files = [];
 
public function updatingPhotos(): void {}
public function updatingFiles(): void {}
 
public function updatedPhotos(): void {}
public function updatedFiles(): void {}

Click here to upload

Accepting only pdf

<x-upload accept="application/pdf" />

Click here to upload

<!-- The listener receive the uploaded file $event.detail.files -->
<x-upload x-on:upload="console.log($event.detail.files)" />
 
<!-- The listener receive the uploaded file $event.detail.file -->
<x-upload delete x-on:remove="console.log($event.detail.file)" />
Static Mode
Although the Upload component was created to handle file uploads, it also allows you to display any type of file that already exists in the application, that is: files that were uploaded at another time. The main benefit of this usage format is that it allows people to view files, including preview images, and can choose to delete them.

1. Use the Livewire component mount method to prepare and store the files in a property that will be bind in the component Blade file:

use Livewire\Component;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\Finder\SplFileInfo;
 
class MyComponent extends Component
{
// For static usage the property must be an array
public $photos = [];
 
public function mount(): void
{
// We get all files and map the contents of the files
// to ensure a necessary structure for the component.
$this->photos = collect(File::allFiles(public_path('storage/images')))->map(fn (SplFileInfo $file) => [
'name' => $file->getFilename(),
'extension' => $file->getExtension(),
'size' => $file->getSize(),
'path' => $file->getPath(),
'url' => Storage::url('images/'.$file->getFilename()),
])->toArray();
 
// In this example we are using the images that exists
// in the application server, but you can use any other
// files for example, files that are stored in the S3 bucket.
}
 
// ...
}

2. Prepare the Blade file of the component:

<!-- All other options is available when static:
label, hint, tip,
footer slot,
events (only remove event)
renaming delete method -->
 
<!-- WITHOUT delete action -->
<x-upload wire:model="photos" static />
 
<!-- WITH delete action -->
<x-upload wire:model="photos" static delete />
 
<!-- You can set a custom placeholder for the input -->
<x-upload wire:model="photos"
:placeholder="count($photos) . ' images'"
static
delete />

3. If you intend to offer the option to delete files, then the approach to deleting files will be a little different from the used when file is uploading, for example:

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\File;
 
public function deleteUpload(array $content): void
{
/*
the $content contains:
[
'temporary_name',
'real_name', // same of 'temporary_name' in static mode
'extension',
'size',
'path',
'url',
]
*/
 
if (empty($this->photos)) {
return;
}
 
File::delete($content['path']);
 
$files = Arr::wrap($this->photos);
 
$this->photos = collect($files)
->filter(fn (array $item) => $item['name'] !== $content['real_name'])
->toArray();
}
This is your images uploaded recently

  • laravel.png

    Size: 91 KB

  • livewire.png

    Size: 4 KB

  • tallstackui.png

    Size: 54 KB

Code highlighting provided by Torchlight