From 410f1c1a84b8843046231de9bbf12522573299f7 Mon Sep 17 00:00:00 2001 From: Vincent LAURENT Date: Thu, 9 Nov 2023 01:22:03 +0100 Subject: [PATCH] organisation: processing is carried out entirely on the javascript side with the pdf-lib js library and not at all on the server side --- app.php | 43 -------------------- public/js/organization.js | 72 +++++++++++++++++++++++++-------- templates/organization.html.php | 6 +-- 3 files changed, 58 insertions(+), 63 deletions(-) diff --git a/app.php b/app.php index 7a233c7..1b1aa21 100644 --- a/app.php +++ b/app.php @@ -353,54 +353,11 @@ $f3->route('GET /cron', function($f3) { if (!$f3->get('disableOrganization')) { $f3->route('GET /organization', function($f3) { - $f3->set('maxSize', min(array(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize'))))); - $f3->set('activeTab', 'organize'); echo View::instance()->render('organization.html.php'); } ); - -$f3->route('POST /organize', - function($f3) { - $filenames = array(); - $tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_organize'); - unlink($tmpfile); - $pages = explode(',', preg_replace('/[^A-Z0-9a-z,]+/', '', $f3->get('POST.pages'))); - - $files = Web::instance()->receive(function($file,$formFieldName){ - if(strpos(Web::instance()->mime($file['tmp_name'], true), 'application/pdf') !== 0) { - $f3->error(403); - } - - return true; - }, false, function($fileBaseName, $formFieldName) use ($tmpfile, &$filenames) { - $filenames[] = str_replace('.pdf', '', $fileBaseName); - - return basename($tmpfile).uniqid().".pdf"; - }); - - if(!count($files)) { - $f3->error(403); - } - - $pdfs = array(); - foreach(array_keys($files) as $i => $file) { - $pdfs[] = chr(65 + $i)."=".$file; - } - - shell_exec(sprintf("pdftk %s cat %s output %s", implode(" ", $pdfs), implode(" ", $pages), $tmpfile.'_final.pdf')); - - Web::instance()->send($tmpfile."_final.pdf", null, 0, TRUE, implode('_', $filenames)); - - if($f3->get('DEBUG')) { - return; - } - - array_map('unlink', glob($tmpfile."*")); - } -); } - $f3->route('GET /metadata', function($f3) { $f3->set('activeTab','metadata'); diff --git a/public/js/organization.js b/public/js/organization.js index 377e266..fda929c 100644 --- a/public/js/organization.js +++ b/public/js/organization.js @@ -209,12 +209,12 @@ var loadPDF = async function(pdfBlob, filename, pdfIndex) { e.stopPropagation(); let container = this.parentNode; let pageValue = container.querySelector('.checkbox-page').value; - let orientation = degreesToOrientation(container.querySelector('.input-rotate').value); + let orientation = container.querySelector('.input-rotate').value; if(orientation) { pageValue = pageValue + "-" + orientation; } document.querySelector('#input_pages').value = pageValue; - document.querySelector('#form_pdf').submit(); + save(); }); canvasContainer.querySelector('.btn-rotate').addEventListener('click', function(e) { e.stopPropagation(); @@ -304,11 +304,16 @@ var getFilesStats = function() { return files; } +const getLetter = function(i) { + + return String.fromCharCode(96 + i+1).toUpperCase(); +} + var updateListePDF = function() { document.querySelector('#list_pdf').innerHTML = ""; let nbFiles = document.querySelector('#input_pdf').files.length; for (var i = 0; i < nbFiles; i++) { - let pdfLetter = String.fromCharCode(96 + i+1).toUpperCase(); + let pdfLetter = getLetter(i); const pdfFile = document.querySelector('#input_pdf').files.item(i); document.querySelector('#list_pdf').insertAdjacentHTML('beforeend', '
  • '+decodeURI(pdfFile.name)+'
  • '); let fileItem = document.querySelector('#file_' + pdfLetter); @@ -537,22 +542,9 @@ var updateGlobalState = function() { } } -var degreesToOrientation = function(degrees) { - if(degrees == 90) { return "east"; } - if(degrees == 180) { return "south"; } - if(degrees == 270) { return "west"; } - - return null; -} - var uploadAndLoadPDF = async function(input_upload) { const cache = await caches.open('pdf'); for (let i = 0; i < input_upload.files.length; i++) { - if(input_upload.files[i].size > maxSize) { - - alert("Le PDF ne doit pas dépasser " + Math.round(maxSize/1024/1024) + " Mo"); - break; - } let filename = input_upload.files[i].name; let response = new Response(input_upload.files[i], { "status" : 200, "statusText" : "OK" }); let urlPdf = '/pdf/'+filename; @@ -563,9 +555,51 @@ var uploadAndLoadPDF = async function(input_upload) { } } +const DL = function (d,f) { + let a = document.createElement("a"), + u = URL.createObjectURL(d); + a.download = f, + a.href = u, + a.click(), + setTimeout(() => URL.revokeObjectURL(u)) +} + +const save = async function () { + const PDFDocument = window['PDFLib'].PDFDocument + const Rotation = window['PDFLib'].Rotation + + const pdf = await PDFDocument.create(); + let filename = ""; + let pdfFiles = []; + for (let i = 0; i < document.querySelector('#input_pdf').files.length; i++) { + if(filename) { + filename += '_'; + } + filename += document.querySelector('#input_pdf').files.item(i).name.replace(/\.pdf$/, ''); + pdfFiles[getLetter(i)] = await PDFDocument.load(await document.querySelector('#input_pdf').files.item(i).arrayBuffer()); + } + + const pages = document.querySelector('#input_pages').value.split(','); + console.log(pages); + for(let i in pages) { + const page = pages[i].split('-')[0]; + const rotation = pages[i].split('-')[1]; + let pdfFile = pdfFiles[page.substr(0,1)]; + const [pdfPage] = await pdf.copyPages(pdfFile, [parseInt(page.substr(1)) - 1]); + if(rotation) { + pdfPage.setRotation(window['PDFLib'].degrees(parseInt(rotation))); + } + pdf.addPage(pdfPage); + } + + const newPDF = new Blob([await pdf.save()], {type: "application/pdf"}); + DL(newPDF, filename+".pdf"); +} + var createEventsListener = function() { document.getElementById('save-select_mobile').addEventListener('click', function(event) { document.getElementById('save-select').click(); + event.preventDefault(); }); document.getElementById('save-select').addEventListener('click', function(event) { let buttonSave = document.getElementById('save'); @@ -574,6 +608,7 @@ var createEventsListener = function() { buttonSave.disabled = false; } buttonSave.click(); + event.preventDefault(); buttonSave.disabled = true; }); document.getElementById('save').addEventListener('click', function(event) { @@ -591,7 +626,7 @@ var createEventsListener = function() { if(checkbox.checked) { pageValue = checkbox.value; } - let orientation = degreesToOrientation(inputRotate.value); + let orientation = inputRotate.value; if(pageValue && orientation) { pageValue = pageValue + "-" + orientation; } @@ -600,9 +635,12 @@ var createEventsListener = function() { } }); document.querySelector('#input_pages').value = order.join(','); + save(); + event.preventDefault(); }); document.getElementById('save_mobile').addEventListener('click', function(event) { document.getElementById('save').click(); + event.preventDefault(); }); document.getElementById('input_pdf_upload_2').addEventListener('change', async function(event) { await uploadAndLoadPDF(this); diff --git a/templates/organization.html.php b/templates/organization.html.php index 2a9d4c6..0727000 100644 --- a/templates/organization.html.php +++ b/templates/organization.html.php @@ -25,10 +25,10 @@

    - + " class="form-control form-control-lg" type="file" accept=".pdf,application/pdf" multiple="true" /> -

    +

     

    @@ -133,7 +133,6 @@ +