Hey there! In this tutorial you will learn how to to create Zip File on the fly with streaming download in PHP Laravel using StechStuido ZipStream package.
Fresh installation of Laravel or working Laravel project. If you want to quick fresh Laravel install with composer using the following command.
composer create-project --prefer-dist laravel/laravel blog
Note: Here I will be downloading the PDF files which I had generate for the invoices. I have written an article on creating PDF in Laravel please have a look at it How To Create / Save / Download PDF From Blade Template In PHP Laravel
StechStudio ZipStream
PackageThe first and the foremost thing to create the ZIP is installing the package. Use the following command to install the pacakge
composer require stechstudio/laravel-zipstream
Following is an example how to use the Zip after downloading the package. I am demoing based on the date range Zip the payment invoices. But you implement as per your requirement, this will give you a rock solid foundation.
use Zip;
class InvoicesController {
public function download()
{
/** Following creates package.zip with file1.pdf, file 2.xlxs */
return Zip::create("package.zip", [
"/path/to/file1.pdf",
"/path/to/file2.xlsx"
]);
}
}
As I had explained in my previous article, we have stored all the PDF's inside public/uploads/invoices
folder
Instead of giving some bullshit examples let me walk you through the real implementation example of invoice project where I have implemented this. In the following code snippet I am filtering all the payments based on the given date range ie fromDate & toDate and then allowing user / admin to zip
files & download his invoices with the given date range.
public function download()
{
/** Validate the date range */
request()->validate([
'from_date' => 'required',
/** Check if to date if greater than that of from date */
'to_date' => 'required|after:from_date',
]);
$fromDate = request('from_date');
$toDate = request('to_date');
/** Get the payment details within the given date range so that we can access the payment invoice name */
$payments = PaymentsController::getSuccessfulPaymentBetweenGivenDateRange($fromDate, $toDate);
/** If no payments the return back with error */
if(count($payments) < 1){
session()->flash('error', 'No invoices were created in the given date range.');
return redirect()->back()->withInput();
}
/** Variable to store List of Invoices names along with public path */
$paymentFiles = [];
foreach($payments as $payment){
/** Store the names of the invoices with full path inside the paymentFiles variable */
$paymentFiles[] = public_path().'/uploads/invoices/'. $payment->invoice_name;
}
/** The following line of code with zip all the invoices from $paymentFiles array */
$zipFilename = "stackcoder_invoices_".$fromDate."-".$toDate.".zip";
return Zip::create($zipFilename, $paymentFiles);
}
This is not the full fledged code of my blade template as there are lot of stuff thats depending on it. But it will give you a good start of how it looks and you can visualise it.
The following code snippet is written in HTML
& Bootstrap 4.x
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
Download invoices in <strong class="text-primary">.zip</strong> format within the given date range.
</div>
<div class="card-body">
@include('errors.custom-error')
<form action="{{ url('invoices/download') }}" method="post">
@csrf
<div class="row form-group">
<div class="col-md-4">
@error('from_date')
<div class="text-danger"> <em>{{ $message }}</em></div>
@enderror
<div class="input-group mb-3">
<input type="text" class="form-control datepicker" autocomplete="off" name="from_date"
value="{{ old('from_date') }}" placeholder="From Date">
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-calendar"></span>
</div>
</div>
</div>
</div>
<div class="col-md-4">
@error('to_date')
<div class="text-danger"> <em>{{ $message }}</em></div>
@enderror
<div class="input-group mb-3">
<input type="text" class="form-control datepicker" autocomplete="off" name="to_date"
value="{{ old('to_date') }}" placeholder="To Date">
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-calendar"></span>
</div>
</div>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-md-12">
<button type="submit" class="btn btn-primary">
<i class="fas fa-cloud-download-alt"></i> Download Invoices
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
In this article you learnt how to create a ZIP
files based on the date range. But it totally depends on your requirements.
Setup MAMP Virtual Hosts For Local PHP Development
Client-Side Form Validation With Javascript
NGINX Security Best Practices & Optimization
Proper Way To Validate MIME Type Of Files While Handling File Uploads In PHP
Run Raw Queries Securely In Laravel
Detect AdBlocker With Javascript And Increase Website Ads Revenue
Why namespace And use Keywords Used In PHP
Laravel 7.x Multiple Database Connections, Migrations, Relationships & Querying
Firebase Cloud Messaging (FCM) Browser Web Push Notifications Using Javascript And PHP
Create Custom 404 Page In Laravel
Sass or SCSS @mixin vs @extends vs Placeholder (%)
Make Laravel Controllers Slim By Skimming Form Validation Request