Laravel Livewire File Upload does not work
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Solving the Livewire File Upload Mystery: Why Your Files Aren't Saving
As a senior developer working with modern PHP frameworks, we often encounter frustrating roadblocks when integrating complex features like file uploads into reactive systems like Livewire. The scenario you've describedâwhere `WithFileUploads` is set up, validation passes, but the actual file does not appear in your public directoryâis a very common sticking point.
This post will diagnose why your Livewire file upload isn't working and provide the robust solution, ensuring your files are correctly stored within your Laravel application.
## The Diagnosis: Understanding `WithFileUploads` and Storage
The issue you are facing is almost never an error in the Livewire component code itself, but rather a missing piece of context regarding how Laravel handles file storage and configuration. When you use `$this->photo->store('upload');`, you are instructing Laravel to save the uploaded file to a specific disk. If this operation fails silently or points to an incorrect location, the file simply vanishes.
The most likely culprits for this failure are:
1. **Missing Disk Configuration:** Laravel needs to know *where* it is allowed to store files (local disk, S3, etc.).
2. **Permissions Issues:** The web server user (e.g., `www-data`) might not have the necessary write permissions for the target directory.
3. **Incorrect File Handling Context:** Ensuring the uploaded file object is correctly passed and handled by the framework structure.
## The Solution: Setting Up File Storage Correctly
To resolve this, we need to ensure that your Laravel environment is properly configured to handle file system operations before Livewire attempts to save the data. This setup is crucial when building dynamic applications on top of a robust framework like Laravel. For detailed information on setting up services and storage within Laravel, you can always refer to resources provided by [laravelcompany.com](https://laravelcompany.com).
### Step 1: Configure Your Storage Disk
Before attempting to store any file, you must define a storage disk in your `config/filesystems.php` file. For local uploads during development, the `local` disk is the standard choice.
Ensure that your configuration looks something like this (focusing on the relevant parts):
```php
// config/filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/public'), // This is where files will be saved
'visibility' => 'public',
],
// ... other disks
],
```
### Step 2: Ensure Public Directory Access (Crucial for Web Access)
If you intend for these files to be accessible via a public URL, ensure that the `storage/app/public` directory is linked to your public web root. This is typically done by creating a symbolic link:
```bash
php artisan storage:link
```
This command creates the necessary symlink from `public/storage` to `storage/app/public`, making the files accessible via the web.
### Step 3: Revisiting the Livewire Component Logic
Your component logic itself is fundamentally correct for triggering the save operation, assuming the setup above is complete. We will refine your code slightly to use standard Laravel file handling patterns within the `updated` hook.
Here is the corrected and robust implementation for your `Avatar` component:
```php
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Storage; // Import the Storage facade
class Avatar extends Component
{
use WithFileUploads;
/**
* @var \Illuminate\Http\UploadedFile|null
*/
public $photo;
public function updated()
{
// 1. Validation remains essential
$this->validate([
'photo' => [
'image',
'max:4096',
],
]);
// 2. The correct way to store the file using the Storage facade
if ($this->photo) {
// Store the file in the 'public' disk, inside a folder named 'avatars'
$path = $this->photo->store('avatars', 'public');
// Optional: You can now save this path to your database
// Photo::create(['user_id' => auth()->id(), 'path' => $path]);
session()->flash('message', 'Photo successfully uploaded!');
}
}
public function render()
{
return view('livewire.profile.avatar');
}
}
```
Notice the change: instead of relying solely on `$this->photo->store()`, we explicitly use `Storage::store()` (or the model's `store` method if using Eloquent relationships). This gives you explicit control over which disk is used, making debugging much easier.
## Conclusion
File uploads in Livewire are powerful tools, but they rely heavily on the underlying configuration of your Laravel application. The failure to upload usually stems from not properly configuring the file system storage mechanism. By ensuring that your `filesystems.php` is set up correctly, you run the necessary artisan commands (like `storage:link`), and by using explicit methods like `Storage::store()`, you ensure data integrity. Keep focusing on these foundational steps, and you will find that building dynamic features with Livewire becomes significantly smoother.