- generazione del PDF riscritto totalmente

- ora è possibile generarlo anche da backend
- FIX: corretto la qualità del PDF e la dimensione non esatta in pixel...
This commit is contained in:
Surya Paolo
2025-05-29 18:23:20 +02:00
parent 9efd193124
commit 40214abe64
12 changed files with 1413 additions and 428 deletions

View File

@@ -60,6 +60,14 @@ const { exec } = require('child_process');
const execPromise = util.promisify(exec);
const GenPdf = require('../modules/GenPdf');
const genPdf = new GenPdf();
(async () => {
await genPdf.launch();
})();
async function updateProductInfo(recproductInfoAttuale, product, idapp, mycatstr) {
if (!recproductInfoAttuale || !mycatstr) return recproductInfoAttuale;
@@ -160,7 +168,7 @@ async function compressPdf(inputFile, outputFile, compressione) {
}
// Valori ammessi per -dPDFSETTINGS di Ghostscript
const validSettings = ['screen', 'ebook', 'printer', 'prepress', 'default'];
const validSettings = ['screen', 'printer', 'high', 'maximum'];
if (!validSettings.includes(compressione)) {
console.warn(`Compressione '${compressione}' non valida, uso 'ebook'`);
compressione = 'ebook';
@@ -228,56 +236,204 @@ async function compressPdfWithPs2Pdf(inputFile, outputFile, compression = 'ebook
}
}
async function convertPDF_GS(inputFile, outputFile, width, height) {
// Verifica che il file di input esista
if (!(await tools.isFileExistsAsync(inputFile))) {
throw new Error(`Il file di input non esiste: ${inputFile}`);
}
// Converti cm in punti (1 cm = 28.34646 punti)
const widthPt = width * 28.34646;
const heightPt = height * 28.34646;
// Arrotonda i valori
const widthPx = Math.round(widthPt);
const heightPx = Math.round(heightPt);
// Comando Ghostscript
const gsCommand = [
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
'-dPDFSETTINGS=/prepress',
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
`-dDEVICEWIDTHPOINTS=${widthPx}`,
`-dDEVICEHEIGHTPOINTS=${heightPx}`,
'-dDPIx=300',
'-dDPIy=300',
`-sOutputFile=${outputFile}`,
inputFile,
].join(' ');
// DIAGNOSI COMPLETA DEL PROBLEMA
async function diagnosePDFProblem() {
console.log('=== DIAGNOSI COMPLETA SISTEMA ===');
// 1. Test ambiente Node.js
console.log('Node.js version:', process.version);
console.log('Platform:', process.platform);
console.log('Architecture:', process.arch);
console.log('Current working directory:', process.cwd());
// 2. Test moduli disponibili
try {
console.log(gsCommand);
await gs.executeSync(gsCommand); // Assicurati che executeSync restituisca una promessa o usa la funzione corretta se è sincrona.
console.log('Conversione completata con successo!');
// Verifica che il file di output sia stato generato
if (await tools.isFileExistsAsync(outputFile)) {
console.log('File di output generato:', outputFile);
} else {
console.error('Il File di output NON è stato generato! :', outputFile);
}
console.log('Testing gs module...');
console.log('gs object:', typeof gs, Object.keys(gs || {}));
} catch (error) {
if (error.code === 'ENOENT') {
throw new Error(`Il file di input non esiste: ${inputFile}`);
} else if (error instanceof gs.GhostscriptError) {
throw new Error(`Errore Ghostscript: ${error.message}`);
} else {
throw new Error(`Errore durante la conversione: ${error.message}`);
}
console.log('gs module error:', error.message);
}
// 3. Test comando di sistema
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);
try {
console.log('Testing gs command from system...');
const { stdout, stderr } = await execAsync('gs -version');
console.log('GS Version stdout:', stdout);
console.log('GS Version stderr:', stderr);
} catch (error) {
console.log('System gs command failed:', error.message);
}
// 4. Test scrittura file
const fs = require('fs').promises;
const path = require('path');
const testFile = path.join(process.cwd(), 'test_write.txt');
try {
await fs.writeFile(testFile, 'test content');
console.log('File write test: SUCCESS');
await fs.unlink(testFile);
} catch (error) {
console.log('File write test: FAILED -', error.message);
}
}
// ALTERNATIVA 1: Usando child_process direttamente
async function convertPDF_ChildProcess(inputFile, outputFile, width, height, compressionLevel = 'screen') {
const { spawn } = require('child_process');
const path = require('path');
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
}
// const widthPt = Math.round(width * 28.34646);
// const heightPt = Math.round(height * 28.34646);
const widthPt = Math.round(width * 28.34646* 10);
const heightPt = Math.round(height * 28.34646 * 10);
// 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${widthPt}x${heightPt}`,
'-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 function extractPdfInfo(inputFile) {
@@ -436,9 +592,11 @@ async function ConvertPDF_Generatore(options, instampa) {
if (options.compressione) {
const mostrainfo = true;
fileout_compressed = tools.removeFileExtension(fileout) + `_compressed.pdf`;
await diagnosePDFProblem();
// await compressPdf(fileout, fileout_compressed, options.compressione);
await compressPdfWithPs2Pdf(fileout, fileout_compressed, options.compressione);
// await compressPdfWithPs2Pdf(fileout, fileout_compressed, options.compressione);
await convertPDF_ChildProcess(fileout, fileout_compressed, options.width, options.height, options.compressione);
// if (mostrainfo) extractPdfInfo(fileout_compressed);
}
@@ -2489,4 +2647,21 @@ router.post('/miab', authenticate, async (req, res) => {
}
});
router.post('/generate-pdf', async (req, res) => {
const { url, filename } = req.body;
if (!url || !filename) {
return res.status(400).json({ error: 'url e filename sono richiesti' });
}
try {
const pdfPath = await genPdf.generatePdfFromUrl(url, filename);
res.download(pdfPath);
} catch (error) {
console.error('Errore generazione PDF:', error);
res.status(500).json({ error: 'Errore generazione PDF' });
}
});
module.exports = router;