dimanche 31 décembre 2017

Comment créer downloader des fichiers de PDF dans CakePHP3

1.  Comment créer uploader dans CakePHP3
2.  Comment créer downloader dans CakePHP3
3.  Comment créer downloader pour des fichiers de PDF dans CakePHP3

D'abord, nous avons besoin de installer libreoffice pour la conversion à PDF et lang-lack de libreoffice:
$ sudo yum install libreoffice libreoffice-langpack-fr

Et éditez la commande de sudo avec visudo et ajoutez "apache ALL=(ALL) NOPASSWD: /usr/bin/libreoffice" dans ce fichier:
$ sudo visudo
(Ajoutez "apache ALL=(ALL) NOPASSWD: /usr/bin/libreoffice" dans ce fichier)

Redémarrer apache:
$ sudo service httpd restart

Ajoutez la fonction suivante dans l'index.ctp:
    function downloadPdf(){
        var files = getSelectedDocuments(true);
        files_not_excel = files.files_notexcel;
        files = files.checkeditems;
        console.log(files);
        if(files.length < 1 || files === undefined){
            alert('Please select at least one Excel document.');
        } else {
            if(files_not_excel.length > 0 && files_not_excel !== undefined){
                var r = confirm("The following files will not be converted to PDF because they are not excel files:\n"
                + files_not_excel.join(', '));
            } else {
                var r = true;
            }
            if(r === true){
                var csrfToken = $('[name=_csrfToken]').val();
                $.ajax({
                    type: "POST",
                    url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "pdfDownload")); ?>',
                    data: {'files' : files},
                    beforeSend: function(xhr){
                        xhr.setRequestHeader('X-CSRF-Token', csrfToken);
                    },
                    success: function(data){
                        var url = '/cake/temp/zip/' + data;
                        console.log(url);
                        download(url);
                    }
                });
            }
        }
    }

Et un bouton pour télécharger fichiers de PDF:
<p><a href="#" onclick="downloadPdf()">Download As PDF</a></p>

L'index.ctp dans l'ensemble:
<?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>
    <p><a href="#" onclick="downloadDocuments()">Download As Zip</a></p>
    <p><a href="#" onclick="downloadPdf()">Download As PDF</a></p>
    <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);
                }
            });
        }
    }
    function downloadPdf(){
        var files = getSelectedDocuments(true);
        files_not_excel = files.files_notexcel;
        files = files.checkeditems;
        console.log(files);
        if(files.length < 1 || files === undefined){
            alert('Please select at least one Excel document.');
        } else {
            if(files_not_excel.length > 0 && files_not_excel !== undefined){
                var r = confirm("The following files will not be converted to PDF because they are not excel files:\n"
                + files_not_excel.join(', '));
            } else {
                var r = true;
            }
            if(r === true){
                var csrfToken = $('[name=_csrfToken]').val();
                $.ajax({
                    type: "POST",
                    url: '<?= $this->Url->build(array("controller" => "Customers", "action" => "pdfDownload")); ?>',
                    data: {'files' : files},
                    beforeSend: function(xhr){
                        xhr.setRequestHeader('X-CSRF-Token', csrfToken);
                    },
                    success: function(data){
                        var url = '/cake/temp/zip/' + data;
                        console.log(url);
                        download(url);
                    }
                });
            }
        }
    }
</script>

Changez le controller de customers et ajoutez les fonctions suivantes comme ça:
    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;
        }
    }

    public function pdfDownload(){
        if ($this->request->is('ajax')) {
            $files = $this->request->data['files'];
            $layout = 'ajax';
            $this->loadModel('Documents');
            $this->autoRender = false;
            try {
                $filesPdf = [];
                $uploadToDirPdf = WWW_ROOT.'temp/zip/';
                $copyFromDirPdf = WWW_ROOT.'uploads/customers/';
                $uploadToDirZip = WWW_ROOT.'temp/zip/';
                $copyFromDirZip = WWW_ROOT;
                foreach($files as $file){
                    $extension = $this->getExtension($file);
                    if(in_array($extension,array_map('strtolower',['xlsx','xlsm','xls']))){
                        $pathPdf = $this->excelToPdf($uploadToDirPdf, $copyFromDirPdf, $file);
                        array_push($filesPdf, $pathPdf);
                    }
                }
                $pathZip = $this->createZip($uploadToDirZip, $copyFromDirZip, $filesPdf);
            }catch(BadRequestException $b){
                //$this->Flash->error(__($b->getMessage()));
            }
            echo $pathZip;
        }
    }

    private function excelToPdf($uploadToDir = null, $copyFromDir = null, $file = null){
        $filePath = explode("/", $file);
        $today = new Date();
        $yearmonth = $today->i18nFormat('yyyyMM');
        $dir = $uploadToDir.$filePath[0];
        if(!file_exists($dir)){
            if(!mkdir($dir, 0755, true)){
                throw new BadRequestException('Couldn\'t make directory.');
            }
            chmod($dir, 0755);
        }
        $command = 'sudo /usr/bin/libreoffice --headless --invisible --norestore --nologo --nofirststartwizard --convert-to pdf --outdir "'
        .$uploadToDir.$filePath[0].'" "'
        .$copyFromDir.$file.'"';
        $result = shell_exec($command);
        if(is_null($result)){
            throw new BadRequestException('pdf couldn\'t be created.');
        }
        $filenameArray = explode(".", $file);
        $filename = "";
        for($i = 0; $i < count($filenameArray)-1; $i++){
            $filename .= $filenameArray[$i];
        }
        return 'temp/zip/'.$filename.'.pdf';
    }

Maintenant vous pouvez télécharger les fichiers comme PDF dans l'index.ctp.




Aucun commentaire:

Enregistrer un commentaire