Laravel Livewire Multiple Files Upload API with Loading and Preview Image

A newer version 1.2.0 is added to Laravel Livewire which consists of File Uploads Components. Before this feature, you have manually use create an event and pass the base64 data to the livewire component.

But in this newer version there is no need to do those steps as you can use WithFileUploads trait which will implicitly create a file object for you and you can also use this to validate, store and also display the preview of the selected image in the template itself.

Note

If you are looking for uploading files using Javascript Invocation in Livewire than you visit this post.

Table of Content

Create New Laravel Project

Run below command to create a new Laravel Project.

composer create-project --prefer-dist laravel/laravel my_new_laravel

After successful installation navigates inside the project through the terminal.

Install and Configure Livewire

After Laravel Project is successfully installed run composer require livewire/livewire to install Livewire.

After this the next step is to publish the config and assets base URL file through which we can specify a custom assets path for livewire package.

php artisan vendor:publish --tag=livewire:config

The above command will publish a config file livewire.php in the config folder inside the project root.

php artisan vendor:publish --tag=livewire:assets

The above command will publish assets for livewire at the path public/vendor folder.

The Livewire official docs recommend adding post-autoload-dump into composer.json inside scripts as shown below.

{
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi",
            "@php artisan vendor:publish --force --tag=livewire:assets --ansi"
        ]
    }
}

Include Livewire Assets into Blade Template

Now you can start developing your project and the first thing you must do is to create a base template that contains livewire javascript assets.

For this let us first create a route.

Route::get('/', function () {
    return view('base');
});

Now create a base.blade.php inside: resources/views/base.blade.php

<html>
<head>
    <title>Laravel File Upload</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
    @livewireStyles
</head>
<body>
    
    @livewireScripts
</body>
</html>

Simple File Upload Component and View

Now the basic setup is done the next thing is to create a simple file upload component and view for this run below command.

php artisan make:livewire file-upload

You’ll see a new file at app/Http/Livewire/FileUpload.php and view at resources/views/livewire/file-upload.blade.php.

After component and view get create you must include them inside base.blade.php.

    @livewireStyles
</head>
<body>

    @livewire('file-upload')

    @livewireScripts
</body>

Simple File Upload Snippet

resources/views/livewire/file-upload.blade.php

<div>
    <h2>File Upload Form</h2>

    <!-- Create File Upload Form -->
    <form wire:submit.prevent="uploadSelectedFile" >
        <div class="row">
            <div class="col-md-3">
                <label for="">Choose File</label>
                <input type="file" wire:model="profile_image" > <!-- Did a mistake here -->
                @error('profile_image') 
                    <span style="color:red;">{{ $message }}</span> 
                @enderror
            </div>
    
            <div class="col-md-12">
                <input type="submit" name="submit" value="Upload Image">
            </div>
        </div>
    </form>
</div>
    

app/Http/Livewire/FileUpload.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Livewire\WithFileUploads;

class FileUpload extends Component
{
    use WithFileUploads;

    public $profile_image;

    public function uploadSelectedFile(){
        $this->validate([
            'profile_image' => 'required|image',
        ]);

        $ext = $this->profile_image->getClientOriginalExtension();
        dd($this->profile_image->storeAs('public/uploads', 'my-profile-pic2.'.$ext));
    }

    public function render()
    { 
        return view('livewire.file-upload');
    }
}    

After this step is done goto URL http://localhost/my_new_laravel/public/ and there you’ll see a file upload form.

The uploaded files will be saved inside storage/app/public directory by folder name uploads.

Laravel will implicitly create the folder if does not exists.

Multiple Files Upload Component, View and with Image Preview

For uploading, multiple files use attribute multiple on the HTML file field.

Create a fresh Multiple File Upload Component with view

php artisan make:livewire multile-files-upload

Change the calling of component file-upload with below component in base.blade.php

<!-- Change from this  -->
@livewire('file-upload')

<!-- TO this  -->
@livewire('multiple-files-upload')

Multiple Files Upload Snippet

resources\views\livewire\multiple-files-upload.blade.php

<div>
    <h2>Multiple Files Uploads</h2>

    <form wire:submit.prevent="uploadMultipleFiles" >
        <div class="row">
            <div class="col-md-3">
                <label for="">Slides</label>
                <input type="file" class="form-control" wire:model="slides" multiple >
                @error('slides.*')
                    <span style="color: red;" >{{ $message }}</span>
                @enderror

                <h2>Preview Images</h2>
                <!-- Loading Message for Images -->
                <div wire:loading wire:target="slides">Uploading Slide Images...</div>
                @if( !empty( $slides ) )
                    <div>
                        @foreach ( $slides as $slide )
                            <img src="{{ $slide->temporaryUrl() }}" alt="" style="width: 100px;" >
                        @endforeach
                    </div>
                @endif 
            </div>

            <div class="col-md-12">
                <button type="submit" class="btn btn-primary" >Upload Slides</button>
            </div>
        </div>
    </form>

</div>

app\Http\Livewire\MultipleFilesUpload.php

<?php

namespace App\Http\Livewire;

use Livewire\Component; 
use Livewire\WithFileUploads;

class MultipleFilesUpload extends Component
{

    use WithFileUploads;

    public $slides=[];

    public function uploadMultipleFiles(){
        $this->validate([
            'slides.*' => 'image'
        ]);

        if( !empty( $this->slides ) ){
            foreach( $this->slides as $slide ){
                $slide->store('public/slides-images');
            }
        }
    }

    public function render()
    {
        return view('livewire.multiple-files-upload');
    }
}

Initialize the public $slides=[]; as an array and after submitting validate each of the files using slides.*. Here the asterisk * means multiple items.

After successful validation loop over $slides and call store() methond on each $slide.

You’ll see that a new folder named slides-images will be created inside storage\app\public and this folder contains all the files you have uploaded.

Previewing Multiple Files before Upload

In template resources\views\livewire\multiple-files-upload.blade.php. The file field is mapped to wire:model=”slides” and onchange the livewire detects the files and displays them when we loop over each of them before the file is just ready to upload.

@if( !empty( $slides ) )
    <div>
        @foreach ( $slides as $slide )
            <img src="{{ $slide->temporaryUrl() }}" alt="" style="width: 100px;" >
        @endforeach
    </div>
@endif 

The path through which images are displayed are stored in $slide->temporaryUrl().

Show loading message before previewing the image

The simplest solution provided by livewire is to use wire:loading directive which has slides as a target.

<div wire:loading wire:target="slides">Uploading Slide Images...</div>

Output

Laravel Livewire multiple files uploads with loading message and previewing of the image before upload final output
Laravel Livewire multiple files uploads with loading message and previewing of the image before upload final output

Conclusion

In conclusion, you have reached the end of this post on the Laravel Livewire Multiple Files Upload API with Loading and Preview Image. For more information or queries comment below.

Summary
Review Date
Reviewed Item
Laravel Livewire Multiple Files Upload API with Loading and Preview Image
Author Rating
51star1star1star1star1star
Software Name
Laravel Livewire Package
Software Name
Windows Os, Mac OS, Linux Os
Software Category
Web Development