// ============================================================================ // n8n Code Node: HTML → PDF через браузер (Puppeteer/Playwright) // ============================================================================ // Используйте этот код ПОСЛЕ ноды, которая вернула HTML или html_base64 // Подготавливает команду для Execute Command ноды с puppeteer // ============================================================================ // Получаем HTML из предыдущей ноды let html = null; // Вариант 1: HTML уже есть в json.html if ($json.html) { html = $json.html; } // Вариант 2: HTML в base64 else if ($json.html_base64) { html = Buffer.from($json.html_base64, 'base64').toString('utf8'); } // Вариант 3: HTML в другом поле else if ($json.body?.html) { html = $json.body.html; } // Вариант 4: Пытаемся получить из binary else if ($binary && $binary.data) { html = $binary.data.toString('utf8'); } else { throw new Error('HTML не найден. Проверьте, что предыдущая нода вернула html или html_base64'); } console.log('📄 HTML получен, длина:', html.length); // ================== ВАРИАНТ 1: Execute Command с Puppeteer ================== // Требует: npm install puppeteer в контейнере n8n // Команда для Execute Command ноды: const htmlBase64 = Buffer.from(html, 'utf8').toString('base64'); const timestamp = Date.now(); const htmlFile = `/tmp/flights-${timestamp}.html`; const pdfFile = `/tmp/flights-${timestamp}.pdf`; // Команда для Execute Command ноды: const command = `node -e " const puppeteer = require('puppeteer'); const fs = require('fs'); const html = Buffer.from('${htmlBase64}', 'base64').toString('utf8'); (async () => { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); await page.setContent(html, { waitUntil: 'networkidle0' }); await page.pdf({ path: '${pdfFile}', format: 'A4', printBackground: true, margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' } }); await browser.close(); const pdfBuffer = fs.readFileSync('${pdfFile}'); const base64 = pdfBuffer.toString('base64'); console.log(base64); fs.unlinkSync('${pdfFile}'); })(); "`; return [{ json: { // Команда для Execute Command ноды command: command, // Или используйте этот вариант (проще): html_file: htmlFile, pdf_file: pdfFile, html_base64: htmlBase64, // Инструкция instruction: 'Используйте Execute Command ноду с одной из команд ниже' } }]; // ================== ВАРИАНТ 2: HTTP Request к сервису с браузером ================== // Раскомментируйте, если используете внешний сервис (Gotenberg, Browserless, etc.) /* const PDF_SERVICE_URL = 'https://api.gotenberg.dev/forms/chromium/convert/html'; // Или Browserless: 'https://chrome.browserless.io/pdf' return [{ json: { method: 'POST', url: PDF_SERVICE_URL, headers: { 'Content-Type': 'multipart/form-data' }, body: { files: [{ name: 'index.html', content: html }], options: { format: 'A4', printBackground: true, margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' } } } } }]; */ // ============================================================================ // ИНСТРУКЦИЯ ПО ИСПОЛЬЗОВАНИЮ: // ============================================================================ // ВАРИАНТ 1: Execute Command (если puppeteer установлен) // 1. Установите puppeteer в контейнере n8n: // docker exec -it npm install puppeteer // 2. Добавьте Execute Command ноду после этого Code Node // 3. В команде используйте: {{ $json.command }} // 4. После Execute Command добавьте Code Node для извлечения base64 из вывода // // ВАРИАНТ 2: HTTP Request к Gotenberg (self-hosted браузер) // 1. Запустите Gotenberg: docker run -p 3000:3000 gotenberg/gotenberg:7 // 2. Используйте код выше (раскомментируйте) // 3. Добавьте HTTP Request ноду // // ВАРИАНТ 3: HTTP Request к Browserless (cloud сервис) // 1. Зарегистрируйтесь на browserless.io // 2. Используйте их API для конвертации // ============================================================================