mirror of
https://github.com/24eme/signaturepdf
synced 2024-05-21 15:16:37 +02:00
organisation: processing is carried out entirely on the javascript side with the pdf-lib js library and not at all on the server side
This commit is contained in:
parent
081832dc84
commit
410f1c1a84
43
app.php
43
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');
|
||||
|
|
|
@ -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', '<li id="file_' + pdfLetter + '" class="list-group-item small ps-2 pe-5" title="'+decodeURI(pdfFile.name)+'" style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden;"><i class="bi bi-files"></i><span class="ms-2">'+decodeURI(pdfFile.name)+'</span> <input class="form-check-input float-end position-absolute file-list-checkbox" type="checkbox" /> </li>');
|
||||
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);
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
<p class="fw-light mb-3 subtitle text-dark text-nowrap" style="overflow: hidden; text-overflow: ellipsis;"><?php echo _("Merge, sort, rotate, delete, extract pages"); ?></p>
|
||||
<div class="col-md-6 col-lg-5 col-xl-4 col-xxl-3 mx-auto">
|
||||
<div class="col-12">
|
||||
<label class="form-label mt-3" for="input_pdf_upload"><?php echo _("Choose a PDF"); ?> <small class="opacity-75" style="cursor: help" title="<?php echo _("The PDF must not exceed "); ?> <?php echo round($maxSize / 1024 / 1024) ?> <?php echo _("Mb"); ?>"><i class="bi bi-info-circle"></i></small></label>
|
||||
<label class="form-label mt-3" for="input_pdf_upload"><?php echo _("Choose a PDF"); ?></label>
|
||||
<input id="input_pdf_upload" placeholder="<?php echo _("Choose a PDF"); ?>" class="form-control form-control-lg" type="file" accept=".pdf,application/pdf" multiple="true" />
|
||||
<p class="mt-2 small fw-light text-dark"><?php echo _("The PDF will be processed by the server without being retained or stored"); ?></p>
|
||||
<?php if($PDF_DEMO_LINK): ?>
|
||||
<p class="mt-2 small fw-light text-dark"> </p>
|
||||
<a class="btn btn-sm btn-link opacity-75" href="#<?php echo $PDF_DEMO_LINK ?>"><?php echo _("Test with a demo PDF"); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
@ -133,7 +133,6 @@
|
|||
<script src="<?php echo $REVERSE_PROXY_URL; ?>/vendor/bootstrap.bundle.min.js?5.1.3"></script>
|
||||
<script src="<?php echo $REVERSE_PROXY_URL; ?>/vendor/pdf.js?legacy"></script>
|
||||
<script>
|
||||
var maxSize = <?php echo $maxSize ?>;
|
||||
var trad = <?php echo json_encode([
|
||||
'Select this page' => _('Select this page'),
|
||||
'Delete this page' => _('Delete this page'),
|
||||
|
@ -146,5 +145,6 @@
|
|||
]); ?>;
|
||||
</script>
|
||||
<script src="<?php echo $REVERSE_PROXY_URL; ?>/js/organization.js?<?php echo ($COMMIT) ? $COMMIT : filemtime($ROOT."/public/js/organization.js") ?>"></script>
|
||||
<script src="<?php echo $REVERSE_PROXY_URL; ?>/vendor/pdf-lib.min.js?1.17.1"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue