Livewire File Upload Tutorial
Published: 2020-12-26 22:05:42

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](https://laravel-livewire.com/docs/2.x/installation).

### Step 1

Create a new component and view from the command line


```ssh
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
<?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:

```php
Use WithFileUploads;
```
Adds the simple magic of uploading files in Livewire.

```php
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.

```php
$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.

```html
<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.

```php
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.