How Livewire Handles File Uploads Without JavaScript: A Practical Guide
Livewire streams uploads to a temporary server folder, letting you validate and store files in one component, with progress events and size‑limit configuration.
14 Oct 2025, 19:41 UTC

Problem: Uploading Files in a Livewire App
When building a Laravel app with Livewire, developers often wonder how to let users attach files without writing a separate AJAX endpoint or juggling hidden iframes. The default approach can be confusing: Livewire seems to “just work” but behind the scenes it streams the file to a temporary server location. Understanding this flow is key to configuring limits, validation, and progress feedback correctly.
Thesis: Livewire’s File‑Upload Pipeline
Livewire’s file‑upload feature automatically:
- Streams the selected file to a temporary disk location on the server.
- Exposes the temporary path via the component’s public property.
- Allows developers to move the file to permanent storage in the
updated()lifecycle hook. - Dispatches
livewire:upload-startandlivewire:upload-finishevents for client‑side progress bars.
Section 1 – Wiring the Component
Create a Livewire component that holds a public $image property. Bind an <input type=\"file\"> to it with wire:model=\"image\". When a file is chosen, Livewire immediately streams it to /storage/livewire-tmp (or the directory defined by config/livewire.php).
// app/Http/Livewire/UploadImage.php
namespace App\Http\Livewire;
use Livewire\Component;
use Livewire\WithFileUploads;
class UploadImage extends Component
{
use WithFileUploads;
public $image;
protected $rules = [
'image' => 'image|max:5120', // 5 MB max
];
public function updatedImage()
{
// Validate immediately after a file is received
$this->validate();
// Move the file to a permanent location
$path = $this->image->store('images', 'public');
session()->flash('message', "Uploaded to {$path}");
}
public function render()
{
return view('livewire.upload-image');
}
}
Notice the WithFileUploads trait – it adds the necessary logic for streaming and temporary storage.
What Happens Under the Hood?
- The browser sends the file via a multipart/form‑data POST to the Livewire endpoint.
- Laravel’s request handling writes the file to the temporary directory before the Livewire component runs.
- Livewire’s
$imageproperty becomes an instance ofLivewire\TemporaryUploadedFile, exposing methods likestore()andgetRealPath(). - After the component finishes, Livewire cleans up the temporary file unless it was moved.
Section 2 – Customizing Size Limits
Livewire’s default maximum upload size is 12 MB, enforced by both PHP’s upload_max_filesize and Livewire’s own configuration. To change it:
- Adjust PHP’s
upload_max_filesizeandpost_max_sizeinphp.inior viaini_set()inpublic/.htaccess. - Override the limit in
config/livewire.php:'max_upload_size' => 10240, // 10 MB in kilobytes - Or set a rule on the component, as shown in the example above.
Always test boundary cases: upload a file just under and just over the limit to ensure the error messages are clear.
Section 3 – Providing Progress Feedback
Because the upload is streamed, Livewire can emit events that the browser can listen to. Add the following JavaScript to your Blade view:
document.addEventListener('livewire:upload-start', event => {
const file = event.detail;
console.log(`Started uploading ${file.name}`);
// Show a progress bar if desired
});
document.addEventListener('livewire:upload-finish', event => {
console.log(`Finished uploading ${event.detail.name}`);
// Hide progress bar
});
These events fire before the file reaches the updated() hook, giving you a window to update the UI without external libraries.
Section 4 – Trade‑offs and Limitations
- Disk Space & Cleanup: The temporary directory must have enough free space and a cleanup routine. Livewire deletes the file after the component finishes, but if the process dies unexpectedly, orphaned files can accumulate.
- Load Balancer & Multiple Instances: If your app runs on several servers behind a load balancer, each instance must share the same temporary directory (e.g., via NFS) or you risk losing the file when a different instance handles the next request.
- Large Files: Files larger than the configured limit or that trigger PHP’s memory limits will cause timeouts. For uploads >10 MB, consider chunked uploads or a dedicated storage service.
- Validation Timing: Validation occurs after the file is streamed. If you need to reject a file before it consumes server space, you’ll need custom client‑side checks.
Actionable Closing
Follow these steps to get a robust Livewire file‑upload flow:
- Define a public property and bind it to an
<input type=\"file\">withwire:model. - Use
WithFileUploadsand setpublic $imageto aTemporaryUploadedFile. - Validate in
rules()orupdatedImage()and move the file withstore(). - Configure
max_upload_sizeinconfig/livewire.phpand test boundary sizes. - Add
livewire:upload-startandlivewire:upload-finishlisteners for progress UI. - Ensure your temporary directory is shared and has a cleanup strategy.
- For very large files, plan a chunked upload strategy or offload to a storage service.
With these patterns, you can deliver a smooth, JavaScript‑free file‑upload experience that scales with your application’s needs.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.