In almost every real-world Laravel project, you eventually bump into this requirement:
“We need to upload multiple images…
…show previews before saving…
…store them somewhere safe…
…and maybe push them to S3 later.”
If you try to do this manually with plain PHP and JavaScript, it quickly turns into a mess of $_FILES, JavaScript event listeners, and validation logic.
With Laravel 12 + Livewire 4, this becomes a lot simpler:
-
Live previews in the browser
-
Server-side validation
-
Easy storage in
public/storage -
Optional upload to Amazon S3 (or any S3-compatible provider like Wasabi / DigitalOcean Spaces)
In this tutorial, you’ll learn how to:
-
Build a Livewire 4 component for multiple image upload
-
Show image previews before saving
-
Save images locally (
storage/app/public) -
Optionally upload images to S3
-
Store image paths in the database
Let’s get started.
1. Prerequisites
You’ll need:
-
Laravel 12 project (PHP 8.2–8.4)
-
Composer
-
Node.js + npm (for asset building if needed)
-
A database configured
-
(Optional) AWS S3 or S3-compatible storage account
I’ll assume you already have Laravel 12 set up and running.
If not, you can create a new project:
2. Install Livewire 4
Install Livewire:
In your main layout (for example resources/views/layouts/app.blade.php), add:
If you’re using a different layout (like your main-fe layout), just make sure both @livewireStyles and @livewireScripts are present.
3. Set Up Local Storage for Images
We’ll store images locally first.
Run:
This creates a symlink:
-
From:
public/storage -
To:
storage/app/public
Anything you store on the public disk will be accessible via /storage/....
4. Create a Migration & Model for Galleries
We’ll create a simple galleries table to store:
-
title(optional) -
images(JSON array of file paths)
Run:
Edit the migration in database/migrations/...create_galleries_table.php:
Run migrations:
Now update app/Models/Gallery.php:
5. Create a Livewire Component for Multiple Image Upload
Generate the component:
This creates:
-
app/Livewire/GalleryUploader.php -
resources/views/livewire/gallery-uploader.blade.php
5.1 Add Logic to GalleryUploader Component
Open app/Livewire/GalleryUploader.php:
Key points:
-
WithFileUploadstrait gives Livewire upload features -
$photosis an array of temporary uploaded files -
saveToLocal()stores images on thepublicdisk -
saveToS3()stores images on thes3disk (we’ll configure this soon)
5.2 Create the Blade View with Preview UI
Open resources/views/livewire/gallery-uploader.blade.php:
This gives you:
-
Multiple file input
-
Live validation
-
Image previews using
temporaryUrl() -
Two buttons: save to local vs save to S3
6. Show the Component in a Page
Create a simple route in routes/web.php:
If you prefer a Blade wrapper:
Then in resources/views/pages/gallery-upload.blade.php:
Adjust layout names to match your project (e.g. layouts.main-fe on your site).
7. Configure S3 (or S3-Compatible) Storage
To support the saveToS3() method, set up your s3 disk.
In .env:
In config/filesystems.php, make sure the s3 disk exists (it usually does by default):
You can swap AWS with Wasabi, DigitalOcean Spaces, etc., by changing the endpoint + credentials. The Livewire code doesn’t change.
8. Displaying the Saved Gallery
Let’s quickly show how to display a saved gallery from local storage.
In a controller or Livewire component:
In a Blade view:
For S3 images, use:
9. Best Practices & Tips
-
Validate every upload:
Always validate file type & size via'photos.*' => 'image|max:2048'. -
Use queues for huge uploads:
For very large batches, consider offloading heavy work to jobs. -
Clean up unused files:
When deleting galleries, also delete images from storage. -
Use meaningful folder names:
e.g.galleries/user-{$user->id}for multi-user systems. -
Hide secrets:
Never commit.envwith real S3 credentials.
10. Conclusion
With Laravel 12 + Livewire 4, multiple file uploads become far less painful:
-
You keep your logic in PHP and Blade.
-
Livewire handles the temporary files and previews.
-
Laravel’s filesystem handles local and cloud storage cleanly.
You’ve built:
-
Multiple image upload UI
-
Live previews
-
Validation
-
Local storage
-
S3 storage
-
Database persistence
From here, you can extend this into:
-
User profile galleries
-
Product image management
-
Admin media libraries
-
Client project galleries