2. How to create downloader in CakePHP3
3. How to create PDF downloader in CakePHP3
Add these functions in the "customers" controller:
(Please note that you need to add these lines also at the top of the controller:
use Cake\I18n\Date;
use ZipArchive;
use Cake\Network\Exception\BadRequestException;
)
private function getExtension($filename){
$temp = explode('.', $filename);
$extension = strtolower(end($temp));
return $extension;
}
public function zipDownload(){
if ($this->request->is('ajax')) {
$layout = 'ajax';
$this->autoRender = false;
$dir = WWW_ROOT . 'temp/zip/';
$copyFromDir = WWW_ROOT.'uploads/customers/';
$files = $this->request->data['files'];
try {
echo $this->createZip($dir, $copyFromDir, $files);
} catch (BadRequestException $e) {
throw $e;
}
}
}
function createZip($uploadToDir = null, $copyFromDir = null, $files = null, $containsYearmonth = false){
if(!file_exists($uploadToDir)){
if(!mkdir($uploadToDir, 0755, true)){
throw new BadRequestException('Can not mkdir.');
}
chmod($uploadToDir, 0755);
}
try {
$zip = new ZipArchive();
$zip_file_name = sha1(time() . rand()).".zip";
$zip_name = $uploadToDir.$zip_file_name; // Zip name
$zip->open($zip_name, ZipArchive::CREATE);
foreach ($files as $file) {
$path = $copyFromDir.$file;
if(file_exists($path)){
$zip->addFromString(basename($path), file_get_contents($path));
}
else{
echo "file does not exist";
}
}
$zip->close();
return $zip_file_name;
} catch (BadRequestException $e) {
throw $e;
}
}
$temp = explode('.', $filename);
$extension = strtolower(end($temp));
return $extension;
}
public function zipDownload(){
if ($this->request->is('ajax')) {
$layout = 'ajax';
$this->autoRender = false;
$dir = WWW_ROOT . 'temp/zip/';
$copyFromDir = WWW_ROOT.'uploads/customers/';
$files = $this->request->data['files'];
try {
echo $this->createZip($dir, $copyFromDir, $files);
} catch (BadRequestException $e) {
throw $e;
}
}
}
function createZip($uploadToDir = null, $copyFromDir = null, $files = null, $containsYearmonth = false){
if(!file_exists($uploadToDir)){
if(!mkdir($uploadToDir, 0755, true)){
throw new BadRequestException('Can not mkdir.');
}
chmod($uploadToDir, 0755);
}
try {
$zip = new ZipArchive();
$zip_file_name = sha1(time() . rand()).".zip";
$zip_name = $uploadToDir.$zip_file_name; // Zip name
$zip->open($zip_name, ZipArchive::CREATE);
foreach ($files as $file) {
$path = $copyFromDir.$file;
if(file_exists($path)){
$zip->addFromString(basename($path), file_get_contents($path));
}
else{
echo "file does not exist";
}
}
$zip->close();
return $zip_file_name;
} catch (BadRequestException $e) {
throw $e;
}
}
And change "index.ctp" in the "Template" folder like this:
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Customer[]|\Cake\Collection\CollectionInterface $customers
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('New Customer'), ['action' => 'add']) ?></li>
</ul>
</nav>
<div class="customers index large-9 medium-8 columns content">
<h3><?= __('Customers') ?></h3>
<div><a href="#" onclick="downloadDocuments()">Download As Zip</a></div>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th scope="col" class="text-center" style="vertical-align: middle;"><?= $this->Form->checkbox('check_all', ['id'=>'check_all']);?></th>
<th scope="col"><?= $this->Paginator->sort('id') ?></th>
<th scope="col"><?= $this->Paginator->sort('name') ?></th>
<th scope="col"><?= $this->Paginator->sort('file_location', 'File') ?></th>
<th scope="col"><?= $this->Paginator->sort('created') ?></th>
<th scope="col"><?= $this->Paginator->sort('modified') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($customers as $customer): ?>
<tr>
<?php $temp = explode('.', $customer->file_location); $extension = strtolower(end($temp)); ?>
<?php $file = ['file_location' => $customer->file_location, 'file_name'=>$customer->name, 'extension'=>$extension] ?>
<td class="text-center"><?= $this->Form->checkbox('checkbox',['name'=>'check_box', 'value'=>h(json_encode($file))]) ?></td>
<td><?= $this->Number->format($customer->id) ?></td>
<td><?= h($customer->name) ?></td>
<td><img src="/cake/uploads/customers/<?= $customer->file_location ?>" width="100" /></td>
<td><?= h($customer->created) ?></td>
<td><?= h($customer->modified) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $customer->id]) ?>
<?= $this->Html->link(__('Edit'), ['action' => 'edit', $customer->id]) ?>
<?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id)]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
$('#check_all').on('click', function() {
$('input:checkbox[name=check_box]').prop('checked', this.checked);
});
});
function getSelectedDocuments(pdfonly){
if (pdfonly === undefined) {
pdfonly = false;
}
var checkeditems = [];
var files_notexcel = [];
$("input[type=checkbox][name=check_box]").each(function(){
if (this.checked) {
var value = JSON.parse($(this).val());
if(pdfonly === true){
var extension = value.extension.toLowerCase();
if($.inArray(extension, ['xlsx','xlsm','xls']) !== -1){
checkeditems.push(value.file_location);
} else {
var name = value.file_location.split("/");
files_notexcel.push(name[name.length - 1]);
}
} else {
checkeditems.push(value.file_location);
}
}
});
var files = {"checkeditems" : checkeditems, "files_notexcel" : files_notexcel};
return files;
}
function download(url){
var link=document.createElement('a');
document.body.appendChild(link);
link.href=url;
link.download = 'download';
link.click();
link.parentNode.removeChild(link);
}
function downloadDocuments(){
var checkeditems = getSelectedDocuments();
checkeditems = checkeditems.checkeditems;
if(checkeditems.length < 1 || checkeditems === undefined){
alert('Please select at least one document.');
} else {
var csrfToken = $('[name=_csrfToken]').val();
$.ajax({
type: "POST",
url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "zipDownload")); ?>',
data: {'files' : checkeditems},
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
},
success: function(data){
var url = '/cake/temp/zip/'+data;
console.log(url);
download(url);
}
});
}
}
</script>
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Customer[]|\Cake\Collection\CollectionInterface $customers
*/
?>
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('New Customer'), ['action' => 'add']) ?></li>
</ul>
</nav>
<div class="customers index large-9 medium-8 columns content">
<h3><?= __('Customers') ?></h3>
<div><a href="#" onclick="downloadDocuments()">Download As Zip</a></div>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th scope="col" class="text-center" style="vertical-align: middle;"><?= $this->Form->checkbox('check_all', ['id'=>'check_all']);?></th>
<th scope="col"><?= $this->Paginator->sort('id') ?></th>
<th scope="col"><?= $this->Paginator->sort('name') ?></th>
<th scope="col"><?= $this->Paginator->sort('file_location', 'File') ?></th>
<th scope="col"><?= $this->Paginator->sort('created') ?></th>
<th scope="col"><?= $this->Paginator->sort('modified') ?></th>
<th scope="col" class="actions"><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($customers as $customer): ?>
<tr>
<?php $temp = explode('.', $customer->file_location); $extension = strtolower(end($temp)); ?>
<?php $file = ['file_location' => $customer->file_location, 'file_name'=>$customer->name, 'extension'=>$extension] ?>
<td class="text-center"><?= $this->Form->checkbox('checkbox',['name'=>'check_box', 'value'=>h(json_encode($file))]) ?></td>
<td><?= $this->Number->format($customer->id) ?></td>
<td><?= h($customer->name) ?></td>
<td><img src="/cake/uploads/customers/<?= $customer->file_location ?>" width="100" /></td>
<td><?= h($customer->created) ?></td>
<td><?= h($customer->modified) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $customer->id]) ?>
<?= $this->Html->link(__('Edit'), ['action' => 'edit', $customer->id]) ?>
<?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id)]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?></p>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
$('#check_all').on('click', function() {
$('input:checkbox[name=check_box]').prop('checked', this.checked);
});
});
function getSelectedDocuments(pdfonly){
if (pdfonly === undefined) {
pdfonly = false;
}
var checkeditems = [];
var files_notexcel = [];
$("input[type=checkbox][name=check_box]").each(function(){
if (this.checked) {
var value = JSON.parse($(this).val());
if(pdfonly === true){
var extension = value.extension.toLowerCase();
if($.inArray(extension, ['xlsx','xlsm','xls']) !== -1){
checkeditems.push(value.file_location);
} else {
var name = value.file_location.split("/");
files_notexcel.push(name[name.length - 1]);
}
} else {
checkeditems.push(value.file_location);
}
}
});
var files = {"checkeditems" : checkeditems, "files_notexcel" : files_notexcel};
return files;
}
function download(url){
var link=document.createElement('a');
document.body.appendChild(link);
link.href=url;
link.download = 'download';
link.click();
link.parentNode.removeChild(link);
}
function downloadDocuments(){
var checkeditems = getSelectedDocuments();
checkeditems = checkeditems.checkeditems;
if(checkeditems.length < 1 || checkeditems === undefined){
alert('Please select at least one document.');
} else {
var csrfToken = $('[name=_csrfToken]').val();
$.ajax({
type: "POST",
url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "zipDownload")); ?>',
data: {'files' : checkeditems},
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
},
success: function(data){
var url = '/cake/temp/zip/'+data;
console.log(url);
download(url);
}
});
}
}
</script>
And you can download the files in index.ctp: