- Finalmente risolto il calcolo e l'impaginazione del PDF, per WEb e per Stampa (300 dpi) !

- corretto altre cose sulla lista cataloghi.
This commit is contained in:
Surya Paolo
2025-05-23 17:02:41 +02:00
parent d6aaaabb00
commit 0e5d28d199
6 changed files with 814 additions and 880 deletions

View File

@@ -19,6 +19,7 @@ mongoose.plugin(schema => {
const IElementiPagina = new Schema({
isTemplate: Boolean,
linkIdTemplate: String,
linkIdTemplatePerStampa: String,
name: String,
pagina: IDimensioni,
});
@@ -83,6 +84,7 @@ const catalogo = new Schema(
print_isTemplate: Boolean,
print_linkIdTemplate: String,
print_linkIdTemplatePerStampa: String,
dimensioni_def: IElementiPagina,

View File

@@ -116,6 +116,7 @@ const scheletroScheda = {
isTemplate: { type: Boolean },
isPagIntro: { type: Boolean },
linkIdTemplate: { type: String },
linkIdTemplatePerStampa: { type: String },
name: { type: String },
numschede_perRiga: { type: Number },
numschede_perCol: { type: Number },

View File

@@ -136,18 +136,7 @@ function updateProductInfoCatProds(productInfo, reccatprod) {
}
}
}
async function compressPdf(inputFile, outputFile, compressione) {
try {
const tempFolder = path.join(cwd, 'temp');
const hasTempFolder = await tools.isFileExistsAsync(tempFolder);
if (!hasTempFolder) {
console.log('creo directory', tempFolder);
await fs.mkdir(tempFolder); // Usa la versione promessa di mkdir
console.log('✅ directory creata', tempFolder);
}
/*
/*
Quando utilizzi Ghostscript per comprimere un PDF e desideri controllare la qualità di stampa, puoi modificare i parametri dell'opzione -dPDFSETTINGS per ottenere risultati migliori per scopi di stampa.
Le seguenti opzioni sono disponibili per -dPDFSETTINGS:
@@ -159,14 +148,49 @@ async function compressPdf(inputFile, outputFile, compressione) {
/default: Usa impostazioni predefinite; generalmente fornisce un buon equilibrio tra qualità e dimensione.
*/
// Comprime il PDF utilizzando Ghostscript
const gsCommand = `gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/${compressione} -dNOPAUSE -dQUIET -dBATCH -sOutputFile="${outputFile}" "${inputFile}"`;
async function compressPdf(inputFile, outputFile, compressione) {
try {
const tempFolder = path.join(cwd, 'temp');
const hasTempFolder = await tools.isFileExistsAsync(tempFolder);
if (!hasTempFolder) {
console.log('creo directory', tempFolder);
await fs.mkdir(tempFolder); // Usa la versione promessa di mkdir
console.log('✅ directory creata', tempFolder);
}
// Valori ammessi per -dPDFSETTINGS di Ghostscript
const validSettings = ['screen', 'ebook', 'printer', 'prepress', 'default'];
if (!validSettings.includes(compressione)) {
console.warn(`Compressione '${compressione}' non valida, uso 'ebook'`);
compression = 'ebook';
}
// Costruisci comando Ghostscript per la compressione PDF
const gsCommand = [
'gs',
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
`-dPDFSETTINGS=/${compressione}`,
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
`-sOutputFile="${outputFile}"`,
`"${inputFile}"`,
].join(' ');
console.log('Compressione del PDF in corso...');
console.log('gsCommand', gsCommand);
// Esegui il comando per la compressione
await execPromise(gsCommand);
// Calcola la percentuale di compressione
const origSize = (await fs.promises.stat(inputFile)).size;
const newSize = (await fs.promises.stat(outputFile)).size;
const percent = Math.round(((origSize - newSize) / origSize) * 100);
console.log(`Il file compresso è circa il ${percent}% più piccolo dell'originale`);
console.log(`PDF compresso e salvato come '${outputFile}'`);
} catch (error) {
console.error('Errore durante la compressione:', error);
@@ -176,7 +200,7 @@ async function compressPdf(inputFile, outputFile, compressione) {
async function convertPDF_GS(inputFile, outputFile, width, height) {
// Verifica che il file di input esista
if (!await tools.isFileExistsAsync(inputFile)) {
if (!(await tools.isFileExistsAsync(inputFile))) {
throw new Error(`Il file di input non esiste: ${inputFile}`);
}
@@ -256,102 +280,16 @@ async function extractPdfInfo(inputFile) {
}
async function convertPDF_PdfLib(idapp, inputFile, outputFile, options) {
if (!await tools.isFileExistsAsync(inputFile)) {
if (!(await tools.isFileExistsAsync(inputFile))) {
throw new Error(`Il file di input non esiste: ${inputFile}`);
}
console.log('START convertPDF_PdfLib...');
try {
// Carica il PDF esistente
const existingPdfBytes = fs.readFileSync(inputFile);
const pdfDoc = await PDFDocument.load(existingPdfBytes);
// Crea un nuovo PDF
const newPdfDoc = await PDFDocument.create();
// Itera attraverso le pagine esistenti
const pages = pdfDoc.getPages();
for (const page of pages) {
const { width: originalWidth, height: originalHeight } = page.getSize();
// Calcola la larghezza e l'altezza in punti
const newWidth = options.width * 72; // Convertito in punti
const newHeight = options.height * 72; // Convertito in punti
// Crea una nuova pagina con le dimensioni specificate
const newPage = newPdfDoc.addPage([newWidth, newHeight]);
// Calcola lo scaling per mantenere le proporzioni
const scaleWidth = newWidth / originalWidth;
const scaleHeight = newHeight / originalHeight;
const scale = Math.min(scaleWidth, scaleHeight); // Usa il min per mantenere il rapporto
// Incorpora la pagina esistente nel nuovo PDF
const embeddedPage = await newPdfDoc.embedPage(page);
// Disegna la pagina incorporata nel nuovo PDF
newPage.drawPage(embeddedPage, {
x: (newWidth - originalWidth * scale) / 2, // Centrato orizzontalmente
y: (newHeight - originalHeight * scale) / 2, // Centrato verticalmente
width: originalWidth * scale,
height: originalHeight * scale,
});
}
let addstr = '';
if (options.compressione) {
addstr = '_temp.pdf';
}
// Salva il nuovo PDF
const pdfBytes = await newPdfDoc.save();
fs.writeFileSync(outputFile + addstr, pdfBytes);
console.log(`PDF convertito e salvato come '${outputFile}'`);
const comprimi = false;
const mostrainfo = true;
let fileout = outputFile;
if (options.compressione) {
const todayDate = tools.getDateYYYYMMDD_Today();
//const compressed = tools.removeFileExtension(outputFile) + `_${todayDate}.pdf`;
const compressed = tools.removeFileExtension(outputFile) + `_generato.pdf`;
await compressPdf(outputFile + addstr, compressed, options.compressione);
if (mostrainfo) extractPdfInfo(compressed);
fileout = compressed;
}
if (options.dir_out && options.idapp) {
// Crea directory se non esiste !
// Salva il fileout anche su questa directory dir_out
//const fileoutdir = path.join(options.dir_out, options.file_out);
//await fs.promises.copyFile(fileout, fileoutdir);
//console.log(`File ${fileout} anche salvato in ${options.dir_out}`);
}
let fileout_print = '';
// Crea anche il PDF per la stampa
if (
options.print_left !== 0 ||
options.print_top !== 0 ||
options.print_right !== 0 ||
options.print_bottom !== 0
) {
options.filenameIn = fileout;
ris = await ConvertPDF_WithMargins(options);
}
const uscita = {
pdf_generato: tools.removePathDirByFileName(options.idapp, fileout),
pdf_generato_stampa: tools.removePathDirByFileName(options.idapp, ris.fileout_print),
};
options.filenameIn = inputFile;
options.filenameOut = outputFile;
const uscita = await ConvertPDF_Generatore(options, options.stampa);
return uscita;
} catch (e) {
@@ -359,20 +297,56 @@ async function convertPDF_PdfLib(idapp, inputFile, outputFile, options) {
return '';
}
}
async function ConvertPDF_WithMargins(options) {
let fileout_print = '';
const marginTop = parseFloat(options.print_top) || 0;
const marginRight = parseFloat(options.print_right) || 0;
const marginBottom = parseFloat(options.print_bottom) || 0;
const marginLeft = parseFloat(options.print_left) || 0;
async function leggiDimensioniPdf(filePath) {
const pdfBytes = await fs.promises.readFile(filePath);
const pdfDoc = await PDFDocument.load(pdfBytes);
const pages = pdfDoc.getPages();
const primaPagina = pages[0];
const { width, height } = primaPagina.getSize();
console.log(
`Dimensioni prima pagina: larghezza = ${tools.arrotondaA2Decimali(
(width / 72) * 25.4
)} mm, altezza = ${tools.arrotondaA2Decimali((height / 72) * 25.4)} mm`
);
return { width, height };
}
async function ConvertPDF_Generatore(options, instampa) {
let fileout = '';
let fileout_compressed = '';
let suffisso_filename = '';
if (!options.filenameIn) {
return { err: 'Nessun file caricato.' };
return { err: 'Nessun file passato in Ingresso.' };
}
const outputFilename = path.basename(tools.removeFileExtension(options.filenameIn)) + '-stampabile.pdf';
const outputPath = path.join(options.dir_out, outputFilename);
let marginTop = instampa ? parseFloat(options.print_top) : 0;
let marginRight = instampa ? parseFloat(options.print_right) : 0;
let marginBottom = instampa ? parseFloat(options.print_bottom) : 0;
let marginLeft = instampa ? parseFloat(options.print_left) : 0;
if (instampa) {
suffisso_filename = '-stampabile';
}
let outputFilename = suffisso_filename
? tools.aggiungiSuffissoAlNomeFile(options.filenameOut, suffisso_filename)
: options.filenameOut;
// controlla se outputFilename non ha directory allora gliela aggiungo
if (!path.dirname(outputFilename)) {
outputFilename = path.join(options.dir_out, outputFilename);
}
const outputFullPathFileName = outputFilename;
await leggiDimensioniPdf(options.filenameIn);
try {
// Leggi il PDF originale
@@ -384,8 +358,12 @@ async function ConvertPDF_WithMargins(options) {
for (let i = 0; i < pages.length; i++) {
const page = pages[i];
// punti PDF (pt), dove 1 punto = 1/72 di pollice.
const { width, height } = page.getSize();
// CONVERTIli in mm e stampa su console
console.log(`Dimensione pagina ${i + 1}: ${(width / 72) * 25.4} mm x ${(height / 72) * 25.4} mm`);
const newWidth = width - marginLeft - marginRight;
const newHeight = height - marginTop - marginBottom;
@@ -408,18 +386,40 @@ async function ConvertPDF_WithMargins(options) {
// Salva il nuovo PDF
const pdfBytes = await destPdfDoc.save();
await fs.promises.mkdir(options.dir_out, { recursive: true });
const dirUscita = path.dirname(outputFullPathFileName);
if (!(await tools.isDirectoryAsync(dirUscita))) {
await fs.promises.mkdir(dirUscita, { recursive: true });
}
await fs.promises.writeFile(outputPath, pdfBytes);
await fs.promises.writeFile(outputFullPathFileName, pdfBytes);
fileout_print = outputPath;
fileout = outputFullPathFileName;
extractPdfInfo(fileout);
if (options.compressione) {
const mostrainfo = true;
// const todayDate = tools.getDateYYYYMMDD_Today();
//const compressed = tools.removeFileExtension(outputFile) + `_${todayDate}.pdf`;
fileout_compressed = tools.removeFileExtension(fileout) + `_compressed.pdf`;
await compressPdf(fileout, fileout_compressed, options.compressione);
// if (mostrainfo) extractPdfInfo(fileout_compressed);
}
} catch (error) {
const log = 'Errore durante la creazione del PDF per la Stampa:' + error.message;
const log = `Errore durante la creazione del PDF: (instampa = ${instampa}): ` + error.message;
console.error(log);
return { err: log, fileout_print: '' };
return {
err: log,
fileout: tools.removePathDirByFileName(options.idapp, fileout),
fileout_compressed: tools.removePathDirByFileName(options.idapp, fileout_compressed),
};
}
return { fileout_print };
return {
fileout: tools.removePathDirByFileName(options.idapp, fileout),
fileout_compressed: tools.removePathDirByFileName(options.idapp, fileout_compressed),
};
}
router.post('/online-pdf', authenticate, async (req, res) => {
@@ -605,76 +605,76 @@ router.post('/convert-pdf', upload.single('pdf'), async (req, res) => {
print_right = '0',
print_bottom = '0',
print_left = '0',
stampa,
salvasufiledascaricare = 'false',
} = req.body;
if (!width) {
await fs.promises.unlink(inputFile);
return res.status(400).send('Width parameter is required');
}
const options = {
width,
height,
compressione,
dir_out,
dir_out: tools.getdirByIdApp(idapp) + '/' + dir_out,
file_out,
idapp,
print_top,
print_right,
print_bottom,
print_left,
stampa: stampa === '1',
};
if (!width) {
fs.unlinkSync(inputFile);
return res.status(400).send('Width parameter is required');
let invia_file_convertito = false;
if (!options.file_out || options.file_out === '') {
options.file_out = `${tools.removeFileExtension(req.file.originalname)}-converted.pdf`;
invia_file_convertito = true;
}
options.dir_out = tools.getdirByIdApp(options.idapp) + '/' + options.dir_out;
// let outputFile = path.join(options.dir_out, `${tools.removeFileExtension(req.file.originalname)}-converted.pdf`);
let outputFile = path.join(options.dir_out, `${options.file_out}`);
let outputFile = path.join(options.dir_out, options.file_out);
try {
await fs.promises.mkdir(DIR_PDF_IN, { recursive: true });
await fs.promises.mkdir(options.dir_out, { recursive: true });
// Converti il PDF
// await convertPDF_GS(inputFile, outputFile, width, height);
const risout = await convertPDF_PdfLib(idapp, inputFile, outputFile, options);
if (!options.dir_out) {
// Invia il file convertito
res.download(risout.pdf_generato, 'output-converted.pdf', (err) => {
if (salvasufiledascaricare === 'true') {
// Invia il file come download
return res.download(outputFile, options.file_out, async (err) => {
await cleanupFiles(inputFile, outputFile);
if (err) {
if (err.code === 'ECONNABORTED' || err.code === 'ECONNRESET') {
console.warn('Richiesta annullata dal client:', err.message);
return;
}
console.error("Errore durante l'invio del file:", err.message || err);
if (!res.headersSent) {
res.status(500).send("Errore durante l'invio del file convertito");
}
} else {
// Rimuovi i file temporanei
cleanupFiles(inputFile, '');
}
});
} else {
cleanupFiles(inputFile, '');
// Non inviare file, solo risposta JSON
await cleanupFiles(inputFile, ''); // pulisci solo inputFile
return res.status(200).send(risout);
}
return res.status(200).send(risout);
} catch (error) {
console.error('Errore durante la conversione:', error);
cleanupFiles(inputFile, '');
await cleanupFiles(inputFile, '');
if (!res.headersSent) {
res.status(500).send(`Errore durante la conversione del PDF: ${error.message}`);
return res.status(500).send(`Errore durante la conversione del PDF: ${error.message}`);
}
}
});
function cleanupFiles(inputFile, outputFile) {
async function cleanupFiles(inputFile, outputFile) {
if (inputFile) {
tools.deleteFile(inputFile).catch((err) => {
await tools.deleteFile(inputFile).catch((err) => {
console.error('Errore durante la rimozione del file di INPUT:', err);
});
}
if (outputFile) {
tools.deleteFile(outputFile).catch((err) => {
await tools.deleteFile(outputFile).catch((err) => {
console.error('Errore durante la rimozione del file di output:', err);
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -546,6 +546,15 @@ module.exports = {
FIRST_PROJ: '__PROJECTS',
EXECUTE_CALCPROJ: true,
isDirectoryAsync: async function (dir) {
try {
const stats = await fs.promises.stat(dir);
return stats.isDirectory();
} catch (e) {
return false;
}
},
isFileExistsAsync: async function (filename) {
try {
let fileExists = await fs.promises
@@ -3999,33 +4008,40 @@ module.exports = {
async deleteFile(filePath) {
try {
await fs.promises.unlink(filePath);
console.log(`File eliminato con successo: ${filePath}`);
// console.log(`File eliminato con successo: ${filePath}`);
} catch (err) {
console.error(`Errore durante l'eliminazione del file: ${filePath}`, err);
throw err;
}
},
delete(mypath, alsothumb, callback) {
fs.unlink(mypath, function (err) {
if (alsothumb) {
try {
let img_small = path.dirname(mypath) + '/' + server_constants.PREFIX_IMG_SMALL + path.basename(mypath);
fs.unlink(img_small, function (err) {
if (err) console.log('Errore durante la Cancellazione del file', mypath);
else console.log('deleted file', mypath);
});
} catch (e) {
console.error(err);
async delete(mypath, alsothumb, callback) {
try {
if (await this.isFileExistsAsync(mypath)) {
await fs.promises.unlink(mypath);
// console.log(`deleted file ${mypath}`);
if (alsothumb) {
let img_small = '';
try {
img_small = path.dirname(mypath) + '/' + server_constants.PREFIX_IMG_SMALL + path.basename(mypath);
if (await this.isFileExistsAsync(img_small)) {
await fs.promises.unlink(img_small);
console.log(`deleted file ${img_small}`);
} else {
// console.warn(`File not found: ${img_small}`);
}
console.log(`deleted file ${img_small}`);
} catch (e) {
console.error(`Error deleting file ${img_small}`, e?.message);
}
}
}
if (err) {
console.error(err);
callback(err);
return;
}
callback();
});
} catch (e) {
console.error(`Error deleting file ${mypath}`, e?.message);
callback(e);
return;
}
callback();
},
async mkdirpath(dirPath) {
@@ -5974,7 +5990,6 @@ module.exports = {
}
}
let fileesistente = false;
if (productInfo.imagefile) {
// controlla se esiste il file
@@ -6102,12 +6117,14 @@ module.exports = {
removePathDirByFileName(idapp, fullfilename) {
const mydir = this.getdirByIdApp(idapp);
// ++ remove mydir from fullfilename and add myhost to generate a URL
const filename = fullfilename.replace(mydir, '').replace(/\\/g, '/'); // Replace backslashes with slashes
let filename = fullfilename.replace(mydir, '').replace(/\\/g, '/'); // Sostituisce backslash con slash
// Rimuove la barra iniziale se presente
if (filename.startsWith('/')) {
filename = filename.substring(1);
}
return filename;
},
isDateValid(mydate) {
try {
return (
@@ -6117,4 +6134,13 @@ module.exports = {
return false;
}
},
aggiungiSuffissoAlNomeFile(filePath, suffisso) {
const dir = path.dirname(filePath);
const estensione = path.extname(filePath);
const nomeFile = path.basename(filePath, estensione);
const nuovoNomeFile = nomeFile + suffisso + estensione;
return path.join(dir, nuovoNomeFile);
},
};

View File

@@ -1219,8 +1219,10 @@ module.exports = {
END_NORMALLY: 1,
END_WITHERROR: -50,
TOOLONGTIME: -10,
}
},
// Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato
PUNTI_PER_POLLICE: 96
};