Livewire V2 File Upload Tutorial

Subscribe to my newsletter and never miss my upcoming articles

In this tutorial, we'll cover uploading a CSV file in Laravel with Livewire. This tutorial is written with the assumption you know how to get a Laravel app up and that Livewire is already installed.

Step 1

Create a new component and view from the command line

artisan livewire:make UploadCsv

This will create two files:

CLASS: app/Http/Livewire/UploadCsv.php

VIEW: resources/views/livewire/upload-csv.blade.php

Step 2

Code up the component. We'll go through the main lines after the snippet

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Livewire\WithFileUploads;

class UploadCsv extends Component
{
    use WithFileUploads;

    public $upload;

    public $description;

    public $sample = [];

    public $rules = [
        'upload' => 'required|mimes:csv,txt|size:1024',
        'description' => 'required'
    ];

    public function save()
    {
        $this->validate();

        // store the csv under the local filesytem, defined in config/filesystems.php
        $this->upload->store('csv', 'local');
    }

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

Let's break it down:

Use WithFileUploads;

Adds the simple magic of uploading files in Livewire.

public $rules = [
   'upload' => 'required|mimes:csv,txt|size:1024',
   'description' => 'required'
];

Adds file validation. Upload and description are required. The uploaded file must be a CSV or txt file and must not be larger than 1 MB.

$this->upload->store('csv', 'local');

By default, Livewire uploads the file to a temporary folder livewire-tmp/. By running store on our upload we can move the file into more permanent storage (file, s3, etc). The above tells Livewire to store the uploaded file using my local drive defined in config/filesystems.php. Further, it will add the new file within a directory called csv.

Step 3

The view.

<div>
    <form wire:submit.prevent="submit">
        <div class="form-group">
            <label>File</label>
            <input type="file" wire:model="upload">

            @error('upload') <span class="error">{{ $message }}</span> @enderror
        </div>
        <div class="form-group">
            <label>File Description</label>
            <input type="input" wire:model="description">

            @error('description') <span class="error">{{ $message }}</span> @enderror
        </div>
        <div class="form-group">
            <button type="submit">Upload</button>
        </div>
    </form>
    <div class="row">
        <div class="col-sm-12">
            @if ($saved)
                <p>The file {{ $upload->getClientOriginalName() }} with the size of {{ round($upload->getSize() / 1024, 0) }} KB has been uploaded!</p>
                <p>The file can be found locally at {{ $saved }}.
            @endif
        </div>
    </div>

Pretty basic Livewire stuff on the view side. wire:submit.prevent="save" will the equivalent of event.preventDefault(). Bind upload and description to the public variables in our component above. @error will display any validation errors from our $rules.

After the file is uploaded it can be handled like any other file upload in Laravel. We can output some information about the file with things like $upload->getClientOriginalName() and $upload->getSize()

Step 4

Add to routes file so we can use it.

Route::get('upload/csv', \App\Http\Livewire\UploadCsv::class);

Upload

If everything worked out you should see this output after uploading a CSV file:

The file test.csv with the size of 10 KB has been uploaded!

The file can be found locally at csv/94Suy9FfeY2iTxHswNw5sfd4G9KPfxIOXb6ArKMm.txt.

In the next version, I'll cover processing the CSV for things like mapping different CSV types to a model.

No Comments Yet