Chunked file uploads with Laravel 10

21-Apr-2023

.

Admin

Chunked file uploads with Laravel 10

Hi friends,

Today, I am going to show you a simple example of how to chunk upload files using Javascript in laravel 10. In this tutorial, you can find how to chunk upload files on a folder by using Javascript in Laravel 10. In this article, we explain how to chunk upload files in laravel 10 using Javascript Example. This example explains to you Laravel 10 – Javascript chunk file upload example tutorial step by step. More than the time we need to save the file data with Javascript request in laravel 10 app without page reload and refresh. In this Laravel 10 Javascript chunk file upload tutorial, I will show you how to upload chunk files using a javascript request. Also, we will see how to validate the file before uploading it to the server.

If you know laravel javascript uploading chunk files in Laravel using javascript and save in the database it too easy. Call the store method with the path at which you wish to store the uploaded chunk file.

We can upload chunk files using Javascript requests in laravel 10 very easily. Let's start our laravel 10 Ajax file upload tutorial from scratch.

Step 1: Download Laravel


Let us begin the tutorial by installing a new laravel application. if you have already created the project, then skip the following step.

composer create-project laravel/laravel example-app

Step 2: Download Playpload

You can download the playpload. Extract the zip file and place the project named larval-file-upload in the public path.

https://www.plupload.com/download

Step 3: Add Migration and Model

Here, we will create migration for "chunk_files" table, let's run the below command and update the code.

php artisan make:migration create_chunk_files_table

database/migrations/2022_03_23_124255_create_chunk_files_table.php

<?php

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\Schema;

return new class extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('chunk_files', function (Blueprint $table) {

$table->id();

$table->string('file');

$table->timestamps();

});

}

/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists('chunk_files');

}

};

Next, run create new migration using Laravel migration command as bellow:

php artisan migrate

Now we will create a File model by using the following command:

php artisan make:model ChunkFile

app/Models/ChunkFile.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Database\Eloquent\Model;

class ChunkFile extends Model

{

use HasFactory;

protected $fillable = [

'file'

];

}

Step 4: Add Controller

In this step, we will create a new FileUploadController; in this file, we will add two methods create() and chunkStore() for render view and store files into folder and database logic.

Let's create ChunkFileController by the following the command:

php artisan make:controller ChunkFileController

Next, let's update the following code to Controller File.

app/Http/Controllers/ChunkFileController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Models\ChunkFile;

class ChunkFileController extends Controller

{

/**

* Write code on Method

*

* @return response()

*/

public function create()

{

return view('chunkUpload');

}

/**

* Write code on Method

*

* @return response()

*/

public function chunkStore(Request $request)

{

$_REQUEST["name"];

$input = $request->all();

// THE UPLOAD DESTINATION - CHANGE THIS TO YOUR OWN

$filePath = storage_path('app/public/upload/testChunk');

if (!file_exists($filePath)) {

if (!mkdir($filePath, 0777, true)) {

return response()->json(["ok"=>0, "info"=>"Failed to create $filePath"]);

}

}

$fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : $_FILES["file"]["name"];

$filePath = $filePath . DIRECTORY_SEPARATOR . $fileName;

// DEAL WITH CHUNKS

$chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;

$chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;

$out = fopen("{$filePath}.part", $chunk == 0 ? "wb" : "ab");

if ($out) {

$in = fopen($_FILES['file']['tmp_name'], "rb");

if ($in) {

while ($buff = fread($in, 4096)) { fwrite($out, $buff); }

} else {

return response()->json(["ok"=>0, "info"=>'Failed to open input stream']);

}

fclose($in);

fclose($out);

unlink($_FILES['file']['tmp_name']);

}

// CHECK IF THE FILE HAS BEEN UPLOADED

if (!$chunks || $chunk == $chunks - 1) {

rename("{$filePath}.part", $filePath);

$array = ['file' => $fileName];

ChunkFile::create($array);

}

$info = "Upload OK";

$ok =1;

return response()->json(["ok"=>$ok, "info"=>$info]);

}

}

Store Files in Storage Folder:

$filePath = storage_path('app/public/upload/testChunk');

Step 5: Add Routes

Furthermore, open the routes/web.php file and add the routes to manage to GET and POST requests for render view and store file logic.

routes/web.php

<?php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\ChunkFileController;

/*

|--------------------------------------------------------------------------

| Web Routes

|--------------------------------------------------------------------------

|

| Here is where you can register web routes for your application. These

| routes are loaded by the RouteServiceProvider within a group which

| contains the "web" middleware group. Now create something great!

|

*/

Route::get('file-upload',[ChunkFileController::class,'create']) ;

Route::post('chunk',[ChunkFileController::class,'chunkStore'])->name('chunk.store');

Step 6: Add Blade File

At the last step we need to create a chunkUpload.blade.php file and in this file, we will create a form with file input Javascript code. So copy it below and put it on that file.

resources/views/chunkUpload.blade.php

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<title>Chunk File Upload in Laravel</title>

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

</head>

<body>

<div class="container mt-5">

<div class="row">

<div class="col-md-12">

<div class="card w-50 m-auto">

<div class="card-header bg-info text-white">

<h4>Chunk File Upload in Laravel</h4>

</div>

<div class="card-body">

<div class="form-group" id="file-input">

<input type="file" id="pickfiles" class="form-control">

<div id="filelist"></div>

</div>

</div>

</div>

</div>

</div>

</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<script src="{{ asset('/plupload/js/plupload.full.min.js') }}"></script>

<script type="text/javascript">

$(document).ready(function () {

var path = "{{ asset('/plupload/js/') }}";

var uploader = new plupload.Uploader({

browse_button: 'pickfiles',

container: document.getElementById('file-input'),

url: '{{ route("chunk.store") }}',

chunk_size: '10kb', // 1 MB

max_retries: 2,

filters: {

max_file_size: '200mb'

},

multipart_params : {

// Extra Parameter

"_token" : "{{ csrf_token() }}"

},

init: {

PostInit: function () {

document.getElementById('filelist').innerHTML = '';

},

FilesAdded: function (up, files) {

plupload.each(files, function (file) {

console.log('FilesAdded');

console.log(file);

document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';

});

uploader.start();

},

UploadProgress: function (up, file) {

console.log('UploadProgress');

console.log(file);

document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";

},

FileUploaded: function(up, file, result){

console.log('FileUploaded');

console.log(file);

console.log(JSON.parse(result.response));

responseResult = JSON.parse(result.response);

if (responseResult.ok==0) {

toastr.error(responseResult.info, 'Error Alert', {timeOut: 5000});

}

if (result.status != 200) {

toastr.error('Your File Uploaded Not Successfully!!', 'Error Alert', {timeOut: 5000});

}

if (responseResult.ok==1 && result.status == 200) {

toastr.success('Your File Uploaded Successfully!!', 'Success Alert', {timeOut: 5000});

}

},

UploadComplete: function(up, file){

// toastr.success('Your File Uploaded Successfully!!', 'Success Alert', {timeOut: 5000});

},

Error: function (up, err) {

// DO YOUR ERROR HANDLING!

toastr.error('Your File Uploaded Not Successfully!!', 'Error Alert', {timeOut: 5000});

console.log(err);

}

}

});

uploader.init();

});

</script>

</body>

</html>

Run Laravel App:

All steps have been done, now you have to type the given command and hit enter to run the Laravel app:

php artisan serve

Now, you have to open the web browser, type the given URL and view the app output:

http://localhost:8000/file-upload

It will help you...

#Laravel 10