Back to Blog 6 min read

Upload Files Using Filepond In Laravel

Today we are going to learn a new and I like the Ux of the filepond library. The way it uploads the files and actions provides the functionalities li...

Today we are going to learn a new and I like the Ux of the filepond library. The way it uploads the files and actions provides the functionalities like editing images as well. You can explore the library here on filepond website.

We will use File Pond with Laravel here. I am working on a product where I had to upload multiple images. I chose File Pond because it provides a very convenient way to interact while uploading.

I first watched the video for File Pond On the Laravel Daily YouTube channel. I'll embed the video so you can watch also you can go to the repo where I have implemented this functionality.

https://www.youtube.com/watch?v=GRXaCfS1qj0
file pond library with laravel

Installing File Pond And Initial Setup

First of all, to start using File Pond we have to use the File Pond Cdn. We also can install this via npm. I'll go with CDN for now.

Requirements

  1. Installed Laravel
  2. Jquery
  3. File pond cdn (I have linked in the snippet below)
  4. Controller ( Temporary File Handler)
  5. Model ( Temporary File Handler)

I have created a welcome.blade.php file where I have used an input to represent file pond actions.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>File Pond Upload</title>
</head>
<link href="https://unpkg.com/filepond/dist/filepond.css" rel="stylesheet">
<link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css" rel="stylesheet">

<body>
    <form action="">
        <input type="file" name="filepond" id="filepond">
    </form>
    {{-- Jquery Library --}}
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    {{-- File Pond Js Cdn --}}
    <script src="https://unpkg.com/filepond/dist/filepond.js"></script>
    {{-- File Pond Jquerys Cdn --}}
    <script src="https://unpkg.com/jquery-filepond/filepond.jquery.js"></script>
    {{-- File Pond Image Preview Cdn --}}
    <script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.js"></script>
    <script>
    FilePond.registerPlugin(FilePondPluginImagePreview);

    $("#filepond").filepond({
        allowImagePreview: true,
        allowImageFilter: true,
        imagePreviewHeight: 100,
        allowMultiple: true,
        allowFileTypeValidation: true,
        allowRevert: true,
        acceptedFileTypes: ["image/png", "image/jpeg", "image/jpg"],
        maxFiles: 5,
        credits: false,
        server: {
            headers: {
                "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
            },
            url: "/temp/upload",
            process: false,
            // revert: true,
            restore: "temp/upload/delete",
            fetch: false,
        },
    });

    </script>
</body>

</html>

Creating Controller And Model

We will create a controller TemporaryFileController and Model TemporaryFile to represent temporary_files table. We also need a migration to create uploaded files.

Migration

You will get to know soon why we need this table.

php artisan make:migration create_temporary_files_table
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('temporary_files', function (Blueprint $table) {
            $table->id();
            $table->string('folder');
            $table->string('filename');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('temporary_files');
    }
};

In FIle Pond when we choose a file after processing it uploads directly to the server. So, in that case, this will return whatever you send in response and keep that until the form is saved in file input.

You can see in the controller below the post method.

Model

php artisan make:model TemporaryFile
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class TemporaryFile extends Model
{
    use HasFactory;

    protected $fillable = ['folder','filename'];
}

Controller

php artisan make:controller TemporaryFileController
<?php

namespace App\Http\Controllers;

use App\Models\TemporaryFile;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TemporaryFileController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        if ($request->isMethod('delete')) {
            $filepond = $request->json()->all();
            $folder = $filepond['folder'];
            $tempFile = TemporaryFile::query()->where('folder', $folder)->first();
            $path = storage_path('app/orders/temp/' . $folder);
            if (is_dir($path) && $tempFile) {
                DB::beginTransaction();

                try {
                    unlink($path . '/' . $tempFile->filename);
                    rmdir($path);
                    $tempFile->delete();
                    DB::commit();

                    return response()->json(['message' => 'success']);
                } catch (\Exception $e) {
                    DB::rollBack();
                    Log::error('Error deleting directory: ' . $e->getMessage());
                    return response()->json(['message' => 'failed'], 500);
                }
            }
            return response()->json(['message' => 'failed'], 500);
        }
        if ($request->hasFile('filepond')) {
            $files  = $request->file('filepond');
            foreach ($files as $key => $file) {
                $filename = $file->getClientOriginalName();
                $folder = uniqid() . '-' . time();
                $file->storeAs('orders/temp/' . $folder, $filename);
                TemporaryFile::query()->create(['folder' => $folder, 'filename' => $filename]);
                // Arr::add($folders, $key, $folder);
                return response()->json(['folder' => $folder], 200);
            }
        }
    }
}

In Controller we are checking if filepond exists then get the file and then we have created a folder name. Now we gonna save this uploaded file in this folder and will return the name of the folder. Well, there's a reason behind returning in json. I was getting some error because of debugbar I guess.

Web.php

<?php

use App\Http\Controllers\TemporaryFileController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

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

Route::controller(TemporaryFileController::class)->group(function(){
    Route::match(['post','delete'],'temp/upload','index')->name('temporary.upload');
});

Error Handling

If you see this kind of error.

That means we are not sending the csrf token in request.

Make sure you have <meta name="csrf-token" content="{{ csrf_token() }}"> this tag in your head so that any time you get this in your js with $('meta[name="csrf-token"]').attr("content"), this syntax.

Now you have to fix this. Update your welcome.blade.php with this tag.

Below is the output:

https://youtu.be/81AQdXUY_bc

Conclusion

Repo URL: https://github.com/robinkashyap-01/filepond-fileupload-laravel

File Pond is an amazing library you should use it if you want to enhance the experience of your application. Thanks.