2025-05-29 18:23:20 +02:00
|
|
|
const puppeteer = require('puppeteer');
|
|
|
|
|
const path = require('path');
|
2025-05-29 19:19:40 +02:00
|
|
|
const { exec } = require('child_process');
|
|
|
|
|
|
2025-05-29 18:23:20 +02:00
|
|
|
const fs = require('fs').promises;
|
|
|
|
|
|
|
|
|
|
const gs = require('ghostscript4js');
|
|
|
|
|
|
|
|
|
|
const { PDFDocument, rgb } = require('pdf-lib');
|
|
|
|
|
|
|
|
|
|
const { Catalog } = require('../models/catalog');
|
|
|
|
|
const { MyPage } = require('../models/mypage');
|
|
|
|
|
|
|
|
|
|
const tools = require('../tools/general');
|
|
|
|
|
const shared_consts = require('../tools/shared_nodejs');
|
|
|
|
|
|
2025-05-29 19:19:40 +02:00
|
|
|
const { compress } = require('compress-pdf');
|
|
|
|
|
|
2025-05-29 18:23:20 +02:00
|
|
|
class GenPdf {
|
|
|
|
|
constructor(idapp) {
|
|
|
|
|
this.idapp = idapp;
|
|
|
|
|
this.browser = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async launch() {
|
2025-05-30 10:49:32 +02:00
|
|
|
this.browser = await puppeteer.launch({
|
|
|
|
|
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
|
|
|
});
|
2025-05-29 18:23:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async close() {
|
|
|
|
|
if (this.browser) {
|
|
|
|
|
await this.browser.close();
|
|
|
|
|
this.browser = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inchesToPixels(inches, stampa) {
|
|
|
|
|
if (stampa) {
|
|
|
|
|
return Math.floor(inches * 300);
|
|
|
|
|
} else {
|
|
|
|
|
return Math.floor(inches * 96);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mmToInches(mm) {
|
|
|
|
|
return mm / 25.4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async autoScroll(page) {
|
2025-05-29 19:19:40 +02:00
|
|
|
console.log('inizia a scrollare');
|
2025-05-30 10:49:32 +02:00
|
|
|
|
|
|
|
|
// Esegui lo scroll fino a quando tutta la pagina non è stata scrollata
|
2025-05-29 18:23:20 +02:00
|
|
|
await page.evaluate(async () => {
|
|
|
|
|
await new Promise((resolve) => {
|
|
|
|
|
let totalHeight = 0;
|
2025-05-30 10:49:32 +02:00
|
|
|
const distance = 100; // distanza dello scroll ad ogni intervallo
|
|
|
|
|
const delay = 40; // tempo di intervallo in ms
|
|
|
|
|
|
|
|
|
|
const scroll = async () => {
|
|
|
|
|
// Esegui lo scroll
|
2025-05-29 18:23:20 +02:00
|
|
|
window.scrollBy(0, distance);
|
|
|
|
|
totalHeight += distance;
|
2025-05-29 19:19:40 +02:00
|
|
|
|
2025-05-30 10:49:32 +02:00
|
|
|
// Verifica se è stato scrollato tutto il corpo della pagina
|
|
|
|
|
if (totalHeight < document.body.scrollHeight) {
|
|
|
|
|
setTimeout(scroll, delay); // Se non è finito lo scroll, continua
|
|
|
|
|
} else {
|
|
|
|
|
resolve(); // Scroll terminato
|
2025-05-29 18:23:20 +02:00
|
|
|
}
|
2025-05-30 10:49:32 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
scroll(); // Avvia lo scroll
|
2025-05-29 18:23:20 +02:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async generatePdfFromUrl(url, filenameOut, options = {}) {
|
|
|
|
|
if (!this.browser) {
|
|
|
|
|
throw new Error('Browser non avviato. Chiama launch() prima.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const page = await this.browser.newPage();
|
2025-05-29 19:19:40 +02:00
|
|
|
const maxTentativi = 3;
|
2025-05-29 18:23:20 +02:00
|
|
|
|
|
|
|
|
try {
|
2025-05-29 19:19:40 +02:00
|
|
|
console.log(`caricamento pagina: ${url}`);
|
2025-05-29 18:23:20 +02:00
|
|
|
await page.goto(url, { waitUntil: 'networkidle0' });
|
2025-05-30 10:49:32 +02:00
|
|
|
|
|
|
|
|
page.on('console', (msg) => {
|
|
|
|
|
if (msg.type() === 'error') {
|
|
|
|
|
console.error('Errore nella pagina:', msg.text());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await tools.attendiNSecondi(8);
|
2025-05-29 19:19:40 +02:00
|
|
|
let success = false;
|
|
|
|
|
let numTentativi1 = 0;
|
|
|
|
|
while (numTentativi1 < maxTentativi) {
|
|
|
|
|
try {
|
|
|
|
|
await page.waitForSelector('.pdf-section', { timeout: 10000 });
|
|
|
|
|
success = true;
|
|
|
|
|
break;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.log(`Tentativo ${numTentativi1 + 1}/${maxTentativi} fallito, ASPETTO DI PIU 10 secondi`);
|
|
|
|
|
await tools.attendiNSecondi(10);
|
|
|
|
|
}
|
|
|
|
|
numTentativi1++;
|
|
|
|
|
}
|
2025-05-29 18:23:20 +02:00
|
|
|
|
|
|
|
|
await this.autoScroll(page);
|
2025-05-29 19:19:40 +02:00
|
|
|
|
2025-05-29 18:23:20 +02:00
|
|
|
await tools.attendiNSecondi(5);
|
|
|
|
|
|
|
|
|
|
// Seleziona tutte le sezioni da stampare
|
|
|
|
|
let sectionHandles = await page.$$('.pdf-section');
|
|
|
|
|
let numTentativi = 0;
|
|
|
|
|
while (sectionHandles.length === 0 && numTentativi < maxTentativi) {
|
2025-05-29 19:19:40 +02:00
|
|
|
console.log(
|
|
|
|
|
`Nessuna sezione .pdf-section trovata nella pagina, quindi ASPETTO DI PIU ${numTentativi + 1}/${maxTentativi}`
|
|
|
|
|
);
|
2025-05-29 18:23:20 +02:00
|
|
|
await tools.attendiNSecondi(5);
|
|
|
|
|
sectionHandles = await page.$$('.pdf-section');
|
|
|
|
|
numTentativi++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sectionHandles.length === 0) {
|
|
|
|
|
throw new Error(`Nessuna sezione .pdf-section trovata nella pagina dopo ${maxTentativi} tentativi`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const pdfBuffers = [];
|
|
|
|
|
|
|
|
|
|
for (const sectionHandle of sectionHandles) {
|
|
|
|
|
// Nascondi tutte le sezioni
|
|
|
|
|
await page.evaluate(() => {
|
|
|
|
|
document.querySelectorAll('.pdf-section').forEach((el) => (el.style.display = 'none'));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Mostra solo la sezione corrente
|
|
|
|
|
await sectionHandle.evaluate((el) => (el.style.display = 'block'));
|
|
|
|
|
|
|
|
|
|
// Calcola dimensioni della sezione
|
|
|
|
|
const { width, height } = await sectionHandle.evaluate((el) => ({
|
|
|
|
|
width: el.scrollWidth, // piccolo padding
|
|
|
|
|
height: el.scrollHeight, // piccolo padding
|
|
|
|
|
}));
|
|
|
|
|
|
2025-05-29 19:19:40 +02:00
|
|
|
// console.log(`Larghezza: ${width}px, Altezza: ${height}px`);
|
2025-05-29 18:23:20 +02:00
|
|
|
|
|
|
|
|
// Imposta viewport dinamico
|
|
|
|
|
await page.setViewport({ width, height });
|
|
|
|
|
|
|
|
|
|
// Genera pdf buffer per questa pagina
|
|
|
|
|
const pdfBuffer = await page.pdf({
|
|
|
|
|
printBackground: true,
|
|
|
|
|
width: `${width}px`,
|
|
|
|
|
height: `${height}px`,
|
|
|
|
|
margin: { top: '0', bottom: '0', left: '0', right: '0' },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
pdfBuffers.push(pdfBuffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unisci tutti i PDF
|
|
|
|
|
const mergedPdf = await PDFDocument.create();
|
|
|
|
|
|
|
|
|
|
for (const pdfBytes of pdfBuffers) {
|
|
|
|
|
const pdf = await PDFDocument.load(pdfBytes);
|
|
|
|
|
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
|
|
|
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mergedPdfFile = await mergedPdf.save();
|
|
|
|
|
|
|
|
|
|
const finalFilePath = path.resolve(process.cwd(), filenameOut);
|
|
|
|
|
await fs.writeFile(finalFilePath, mergedPdfFile);
|
|
|
|
|
|
|
|
|
|
// Ripristina tutte le sezioni visibili
|
|
|
|
|
await page.evaluate(() => {
|
|
|
|
|
document.querySelectorAll('.pdf-section').forEach((el) => (el.style.display = 'block'));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log(`PDF finale generato: ${finalFilePath}`);
|
|
|
|
|
|
|
|
|
|
return finalFilePath;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Errore durante generazione PDF:', error);
|
|
|
|
|
throw error;
|
|
|
|
|
} finally {
|
|
|
|
|
await page.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async convertPDF_ChildProcess(inputFile, outputFile, widthpx, heightpx, compressionLevel = 'screen') {
|
|
|
|
|
const { spawn } = require('child_process');
|
|
|
|
|
const path = require('path');
|
|
|
|
|
|
|
|
|
|
widthpx = widthpx * 2;
|
|
|
|
|
heightpx = heightpx * 2;
|
|
|
|
|
|
|
|
|
|
console.log('=== CONVERSIONE CON CHILD_PROCESS E COMPRESSIONE ===');
|
|
|
|
|
|
|
|
|
|
// Verifica input
|
|
|
|
|
if (!(await tools.isFileExistsAsync(inputFile))) {
|
|
|
|
|
throw new Error(`File input non trovato: ${inputFile}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Assicurati che la directory output esista
|
|
|
|
|
const outputDir = path.dirname(outputFile);
|
|
|
|
|
const fs = require('fs').promises;
|
|
|
|
|
try {
|
|
|
|
|
await fs.mkdir(outputDir, { recursive: true });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// Directory già esistente, ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parametri di compressione ottimizzati
|
|
|
|
|
const compressionSettings = {
|
|
|
|
|
/*maximum: [
|
|
|
|
|
'-dPDFSETTINGS=/screen',
|
|
|
|
|
'-dDownsampleColorImages=true',
|
|
|
|
|
'-dColorImageResolution=72',
|
|
|
|
|
'-dDownsampleGrayImages=true',
|
|
|
|
|
'-dGrayImageResolution=72',
|
|
|
|
|
'-dDownsampleMonoImages=true',
|
|
|
|
|
'-dMonoImageResolution=72',
|
|
|
|
|
],
|
|
|
|
|
high: [
|
|
|
|
|
'-dPDFSETTINGS=/ebook',
|
|
|
|
|
'-dDownsampleColorImages=true',
|
|
|
|
|
'-dColorImageResolution=150',
|
|
|
|
|
'-dDownsampleGrayImages=true',
|
|
|
|
|
'-dGrayImageResolution=150',
|
|
|
|
|
],*/
|
|
|
|
|
printer: ['-dPDFSETTINGS=/printer', '-dDownsampleColorImages=true', '-dColorImageResolution=300'],
|
|
|
|
|
screen: [
|
|
|
|
|
'-dPDFSETTINGS=/screen',
|
|
|
|
|
'-dDownsampleColorImages=true',
|
|
|
|
|
'-dColorImageResolution=96',
|
|
|
|
|
'-dDownsampleGrayImages=true',
|
|
|
|
|
'-dGrayImageResolution=96',
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const args = [
|
|
|
|
|
'-sDEVICE=pdfwrite',
|
|
|
|
|
'-dCompatibilityLevel=1.4',
|
|
|
|
|
'-dNOPAUSE',
|
|
|
|
|
'-dQUIET',
|
|
|
|
|
'-dBATCH',
|
|
|
|
|
'-dSAFER',
|
|
|
|
|
|
|
|
|
|
// Parametri di compressione
|
|
|
|
|
...(compressionSettings[compressionLevel] || compressionSettings['screen']),
|
|
|
|
|
'-dCompressFonts=true',
|
|
|
|
|
'-dSubsetFonts=true',
|
|
|
|
|
'-dColorImageFilter=/DCTEncode',
|
|
|
|
|
'-dGrayImageFilter=/DCTEncode',
|
|
|
|
|
'-dEmbedAllFonts=true',
|
|
|
|
|
|
|
|
|
|
// Dimensioni pagina
|
|
|
|
|
`-g${widthpx}x${heightpx}`,
|
|
|
|
|
'-dFIXEDMEDIA',
|
|
|
|
|
// '-dPDFFitPage',
|
|
|
|
|
|
|
|
|
|
// Output
|
|
|
|
|
`-sOutputFile=${outputFile}`,
|
|
|
|
|
inputFile,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
console.log('Spawning gs with compression args:', args.join(' '));
|
|
|
|
|
|
|
|
|
|
const gsProcess = spawn('gs', args, {
|
|
|
|
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
|
|
|
shell: process.platform === 'win32',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let stdout = '';
|
|
|
|
|
let stderr = '';
|
|
|
|
|
|
|
|
|
|
gsProcess.stdout.on('data', (data) => {
|
|
|
|
|
stdout += data.toString();
|
|
|
|
|
if (stdout.length < 1000) {
|
|
|
|
|
// Evita log troppo lunghi
|
|
|
|
|
console.log('GS OUT:', data.toString().trim());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
gsProcess.stderr.on('data', (data) => {
|
|
|
|
|
stderr += data.toString();
|
|
|
|
|
if (stderr.length < 1000) {
|
|
|
|
|
console.log('GS ERR:', data.toString().trim());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
gsProcess.on('close', async (code) => {
|
|
|
|
|
console.log(`GS process closed with code: ${code}`);
|
|
|
|
|
|
|
|
|
|
if (code === 0) {
|
|
|
|
|
// Attendi e verifica
|
|
|
|
|
setTimeout(async () => {
|
|
|
|
|
try {
|
|
|
|
|
const exists = await tools.isFileExistsAsync(outputFile);
|
|
|
|
|
if (exists) {
|
|
|
|
|
// Verifica dimensioni per confermare compressione
|
|
|
|
|
try {
|
|
|
|
|
const originalStats = await tools.getFileStatsAsync(inputFile);
|
|
|
|
|
const newStats = await tools.getFileStatsAsync(outputFile);
|
|
|
|
|
const compressionRatio = (((originalStats.size - newStats.size) / originalStats.size) * 100).toFixed(
|
|
|
|
|
1
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.log(`📁 File originale: ${(originalStats.size / 1024 / 1024).toFixed(2)} MB`);
|
|
|
|
|
console.log(`📁 File compresso: ${(newStats.size / 1024 / 1024).toFixed(2)} MB`);
|
|
|
|
|
console.log(`🗜️ Compressione: ${compressionRatio}%`);
|
|
|
|
|
console.log('✅ SUCCESS: File generato e compresso');
|
|
|
|
|
} catch (statsError) {
|
|
|
|
|
console.log('Warning: impossibile calcolare statistiche compressione');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resolve(outputFile);
|
|
|
|
|
} else {
|
|
|
|
|
console.log('❌ FAIL: File non generato nonostante exit code 0');
|
|
|
|
|
reject(new Error('File non generato nonostante successo processo'));
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
reject(error);
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
} else {
|
|
|
|
|
reject(new Error(`Ghostscript failed with code ${code}: ${stderr}`));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
gsProcess.on('error', (error) => {
|
|
|
|
|
console.log('GS process error:', error);
|
|
|
|
|
reject(new Error(`Failed to start Ghostscript: ${error.message}`));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async generatePdfFromUrls(urls, outputFilename) {
|
|
|
|
|
if (!this.browser) {
|
|
|
|
|
throw new Error('Browser non avviato. Chiama launch() prima.');
|
|
|
|
|
}
|
|
|
|
|
const pdfBuffers = [];
|
|
|
|
|
|
|
|
|
|
outputFilename = tools.getdirByIdApp(idapp) + '/';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
for (const url of urls) {
|
|
|
|
|
// ............
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mergedPdf = await PDFDocument.create();
|
|
|
|
|
|
|
|
|
|
for (const pdfBytes of pdfBuffers) {
|
|
|
|
|
const pdf = await PDFDocument.load(pdfBytes);
|
|
|
|
|
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
|
|
|
|
|
copiedPages.forEach((page) => mergedPdf.addPage(page));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const mergedPdfFile = await mergedPdf.save();
|
|
|
|
|
|
|
|
|
|
const outputPath = path.resolve(process.cwd(), outputFilename);
|
|
|
|
|
await fs.writeFile(outputPath, mergedPdfFile);
|
|
|
|
|
|
|
|
|
|
console.log(`PDF unito generato: ${outputPath}`);
|
|
|
|
|
return outputPath;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Errore durante la generazione PDF:', error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async getPathByPage(idpage) {
|
|
|
|
|
const mypage = await MyPage.findById(idpage);
|
|
|
|
|
|
|
|
|
|
if (mypage) {
|
|
|
|
|
return mypage.path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async generatePdfFromIdCatalog(options) {
|
|
|
|
|
try {
|
|
|
|
|
if (!options) {
|
|
|
|
|
console.error('Opzioni non passate !');
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
let filenamerelative = '';
|
|
|
|
|
let fullnamepath = '';
|
2025-05-29 19:19:40 +02:00
|
|
|
let fullnamepath_compr = '';
|
|
|
|
|
let filenamerelative_compressed = '';
|
2025-05-29 18:23:20 +02:00
|
|
|
let stampa = options.stampa;
|
|
|
|
|
|
|
|
|
|
/*if (stampa) {
|
|
|
|
|
options.width = '227.3mm';
|
|
|
|
|
options.height = '313.5mm';
|
|
|
|
|
} else {
|
|
|
|
|
options.width = '210mm';
|
|
|
|
|
options.height = '297mm';
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
const catalog = await Catalog.findById(options.idCatalog);
|
|
|
|
|
if (catalog) {
|
2025-05-29 19:19:40 +02:00
|
|
|
const url =
|
2025-05-30 10:49:32 +02:00
|
|
|
tools.getHostByIdApp(this.idapp) +
|
|
|
|
|
'/cataloghi?id=' +
|
|
|
|
|
catalog._id +
|
|
|
|
|
'&stampa=' +
|
|
|
|
|
(stampa ? '1' : '0') +
|
|
|
|
|
'&hideHeader=1';
|
2025-05-29 18:23:20 +02:00
|
|
|
|
|
|
|
|
if (url) {
|
|
|
|
|
const myfilenameout = await this.getPathByPage(catalog.idPageAssigned);
|
|
|
|
|
|
2025-05-29 19:19:40 +02:00
|
|
|
let addstr = stampa ? '_stampabile' : '';
|
2025-05-29 18:23:20 +02:00
|
|
|
|
|
|
|
|
filenamerelative = options.path + `${myfilenameout}${addstr}_generato.pdf`;
|
|
|
|
|
|
|
|
|
|
fullnamepath = tools.getdirByIdApp(this.idapp) + '/' + filenamerelative;
|
|
|
|
|
await this.generatePdfFromUrl(url, fullnamepath, options);
|
2025-05-29 19:19:40 +02:00
|
|
|
|
|
|
|
|
if (options.comprimi) {
|
|
|
|
|
filenamerelative_compressed = options.path + `${myfilenameout}${addstr}_generato_compressed.pdf`;
|
|
|
|
|
fullnamepath_compr = tools.getdirByIdApp(this.idapp) + '/' + filenamerelative_compressed;
|
|
|
|
|
await this.compressPdf(fullnamepath, fullnamepath_compr, options.compressione);
|
|
|
|
|
}
|
2025-05-29 18:23:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-29 19:19:40 +02:00
|
|
|
return {
|
|
|
|
|
fileout: filenamerelative,
|
|
|
|
|
fileout_compressed: filenamerelative_compressed,
|
|
|
|
|
filesize: await tools.getSizeFile(fullnamepath),
|
|
|
|
|
filesize_compressed: await tools.getSizeFile(fullnamepath_compr),
|
2025-05-30 10:49:32 +02:00
|
|
|
error: '',
|
2025-05-29 19:19:40 +02:00
|
|
|
};
|
2025-05-29 18:23:20 +02:00
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Errore durante la generazione del PDF dal catalogo ID:', error);
|
2025-05-29 19:19:40 +02:00
|
|
|
return {
|
|
|
|
|
fileout: '',
|
|
|
|
|
filesize: 0,
|
|
|
|
|
error: 'Errore durante la generazione del PDF dal catalogo ID:' + error?.message,
|
|
|
|
|
};
|
2025-05-29 18:23:20 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-30 10:49:32 +02:00
|
|
|
return { fileout: '', filesize: 0, error: '' };
|
2025-05-29 19:19:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async compressPdf(inputPath, outputPath, compressione = 'printer') {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
// Risolvi i percorsi assoluti
|
|
|
|
|
const inputFile = path.resolve(inputPath);
|
|
|
|
|
const outputFile = path.resolve(outputPath);
|
|
|
|
|
|
|
|
|
|
const validQualities = ['screen', 'ebook', 'printer', 'prepress', 'default'];
|
2025-05-30 10:49:32 +02:00
|
|
|
if (!validQualities.includes(compressione)) compressione = 'screen';
|
2025-05-29 19:19:40 +02:00
|
|
|
|
|
|
|
|
// Comando Ghostscript per compressione - impostazione per web (/screen)
|
|
|
|
|
const gsCommand = `gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/${compressione} -dNOPAUSE -dBATCH -dQUIET -sOutputFile="${outputFile}" "${inputFile}"`;
|
|
|
|
|
|
|
|
|
|
console.log('Eseguo comando:', gsCommand);
|
|
|
|
|
|
|
|
|
|
exec(gsCommand, (error, stdout, stderr) => {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error(`Errore compressione PDF: ${error.message}`);
|
|
|
|
|
return reject(error);
|
|
|
|
|
}
|
|
|
|
|
if (stderr) {
|
|
|
|
|
console.error(`Ghostscript stderr: ${stderr}`);
|
|
|
|
|
}
|
|
|
|
|
console.log(`Compressione completata. File salvato in: ${outputFile}`);
|
|
|
|
|
resolve(outputFile);
|
|
|
|
|
});
|
|
|
|
|
});
|
2025-05-29 18:23:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = GenPdf;
|