How to Upload Large Files in Laravel Web Application?

Hassan Raza
3 min readJul 20, 2021

--

Uploading files is a necessary part of almost every web application and it is important to handle file uploading efficiently, especially large files.

In one of my recent Laravel projects, I was struggling to upload large files let’s say 4GB. I tried increasing the below variables in php.ini, but it didn’t work well.

upload_max_filesize = 5000M
post_max_size = 5000M
max_input_time = 3000
max_execution_time = 3000

Then I found an efficient solution (Upload large files in chunks) in which I used resumable.js and laravel-chunk-upload and now I can upload larage files even 10GB or more without any issue. Don’t want to read more? Watch the video below.

How To Upload Large Files in Laravel

1# Frontend setup

First of all, we will set up our frontend to send large files in chunks to backend

https://cdn.jsdelivr.net/npm/resumablejs@1.1.0/resumable.min.js
  • Write HTML code to pick and display file (video file in my case)
<div class="container pt-4">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header text-center">
<h5>Upload File</h5>
</div>

<div class="card-body">
<div id="upload-container" class="text-center">
<button id="browseFile" class="btn btn-primary">Brows File</button>
</div>
<div style="display: none" class="progress mt-3" style="height: 25px">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 75%; height: 100%">75%</div>
</div>
</div>

<div class="card-footer p-4" style="display: none">
<video id="videoPreview" src="" controls style="width: 100%; height: auto"></video>
</div>
</div>
</div>
</div>
</div>
  • Write JavaScript to upload large files via resumable in chunks
<script type="text/javascript">
let browseFile = $('#browseFile');
let resumable = new Resumable({
target: '{{ route('files.upload.large') }}',
query:{_token:'{{ csrf_token() }}'} ,// CSRF token
fileType: ['mp4'],
chunkSize: 10*1024*1024, // default is 1*1024*1024, this should be less than your maximum limit in php.ini
headers: {
'Accept' : 'application/json'
},
testChunks: false,
throttleProgressCallbacks: 1,
});

resumable.assignBrowse(browseFile[0]);

resumable.on('fileAdded', function (file) { // trigger when file picked
showProgress
();
resumable.upload() // to actually start uploading.
});

resumable.on('fileProgress', function (file) { // trigger when file progress update
updateProgress
(Math.floor(file.progress() * 100));
});

resumable.on('fileSuccess', function (file, response) { // trigger when file upload complete
response = JSON.parse(response)
$('#videoPreview').attr('src', response.path);
$('.card-footer').show();
});

resumable.on('fileError', function (file, response) { // trigger when there is any error
alert
('file uploading error.')
});


let progress = $('.progress');
function showProgress() {
progress.find('.progress-bar').css('width', '0%');
progress.find('.progress-bar').html('0%');
progress.find('.progress-bar').removeClass('bg-success');
progress.show();
}

function updateProgress(value) {
progress.find('.progress-bar').css('width', `${value}%`)
progress.find('.progress-bar').html(`${value}%`)
}

function hideProgress() {
progress.hide();
}
</script>

2# The backend setup

Now we will set up our backend (Laravel) to accept chunks and merge them at the end using laravel-chunk-upload

composer require pion/laravel-chunk-upload
  • Write controller function to accept and save file chunks and merge them when all chunks are received.
public function uploadLargeFiles(Request $request) {
$receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));

if (!$receiver->isUploaded()) {
// file not uploaded
}

$fileReceived = $receiver->receive(); // receive file
if
($fileReceived->isFinished()) { // file uploading is complete / all chunks are uploaded
$file = $fileReceived->getFile(); // get file
$extension = $file->getClientOriginalExtension();
$fileName = str_replace('.'.$extension, '', $file->getClientOriginalName()); //file name without extenstion
$fileName .= '_' . md5(time()) . '.' . $extension; // a unique file name

$disk = Storage::disk(config('filesystems.default'));
$path = $disk->putFileAs('videos', $file, $fileName);

// delete chunked file
unlink
($file->getPathname());
return [
'path' => asset('storage/' . $path),
'filename' => $fileName
];
}

// otherwise return percentage information
$handler = $fileReceived->handler();
return [
'done' => $handler->getPercentageDone(),
'status' => true
];
}

I hope this article will help you upload large files in Laravel as it helps me 😊.
Good Luck & Happy Coding
Hassan Raza

--

--

Hassan Raza

I’m a software engineer, full-stack developer, and freelancer with having a passion to develop innovative programs and a love to explore new things.