Задать вопрос
@html_student
Молодой и глупый.

Не корректно считает высоту pdf puppeteer?

Написал маленькое приложение которое генерит пдф со страницы. Сама страница динамическая. Разной высоты.

const express = require('express');
const bodyParser = require('body-parser');
const puppeteer = require('puppeteer');

const app = express();
app.use(bodyParser.json({ limit: '10mb' }));

app.post('/generate', async (req, res) => {
    const { html, options } = req.body;
    if (!html) {
        return res.status(400).send('No HTML provided');
    }

    try {
        const browser = await puppeteer.launch({
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });
       
        const page = await browser.newPage();
        await page.setViewport({
            width: 720,
            deviceScaleFactor: 1,
            height: 1500 // просто временно!
        });
        await page.setContent(html, { waitUntil: 'networkidle0' });

        const scrollHeight = await page.evaluate(() => {
            const main = document.querySelector('main.generator.page');
            return main ? main.scrollHeight : document.body.scrollHeight;
        });


        const pdf = await page.pdf({
            width: '720px',
            height: `${scrollHeight}px`,
            printBackground: true,
            ...options
        });

        await browser.close();

        res.set({
            'Content-Type': 'application/pdf',
            'Content-Disposition': 'attachment; filename="file.pdf"',
        });
        res.send(pdf);
    } catch (e) {
        console.error('PDF generation error:', e);
        res.status(500).send(e.toString());
    }
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
    console.log(`PDF generator listening on port ${PORT}`);
});


Запустил приложение, но с высотой страницы не понятно. пытаюсь scrollHeight расчитать по контейнеру. То он сохраняет вроде нормально, то белое пустое место снизу оставляет прям в разы больше. Не понимаю с чем это связано.
По ширине все норм, макет фиксированный 720px

обложился логами.

const express = require('express');
const bodyParser = require('body-parser');
const puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');

const app = express();
app.use(bodyParser.json({ limit: '10mb' }));

// Функция для записи логов
function logToFile(message) {
    const logPath = path.join(__dirname, 'log.txt');
    const timestamp = new Date().toISOString();
    const logMessage = `[${timestamp}] ${message}\n`;

    fs.appendFile(logPath, logMessage, (err) => {
        if (err) console.error('Ошибка записи в лог:', err);
    });
}

console.log('Доступные методы Page:', Object.keys(require('puppeteer').Page.prototype));

app.post('/generate', async (req, res) => {
    const { html, options } = req.body;
    if (!html) {
        logToFile('Ошибка: Не предоставлен HTML');
        return res.status(400).send('No HTML provided');
    }

    try {
        logToFile('Запуск браузера Puppeteer...');
        const browser = await puppeteer.launch({
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });

        const page = await browser.newPage();
        await page.setViewport({
            width: 720,
            deviceScaleFactor: 1,
            height: 1 // Минимальная высота
        });

        logToFile('Установка HTML-контента...');
        await page.setContent(html, { waitUntil: 'networkidle0' });
        
        await new Promise(r => setTimeout(r, 500)); // Доп. задержка

        logToFile('Вычисление высоты содержимого...');
        const scrollHeight = await page.evaluate(() => {
            const main = document.querySelector('main.generator.page') || document.body;
            return main.scrollHeight;
        });

        logToFile(`Высота PDF: ${scrollHeight}px`);
        const pdf = await page.pdf({
            width: '720px',
            height: `${scrollHeight + 1}px`, // +1px
            printBackground: true,
            ...options
        });

        await browser.close();
        logToFile('PDF успешно сгенерирован');

        res.set({
            'Content-Type': 'application/pdf',
            'Content-Disposition': 'attachment; filename="file.pdf"',
        });
        res.send(pdf);
    } catch (e) {
        logToFile(`Ошибка генерации PDF: ${e.toString()}`);
        console.error('PDF generation error:', e);
        res.status(500).send(e.toString());
    }
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
    logToFile(`Сервер запущен на порту ${PORT}`);
    console.log(`PDF generator listening on port ${PORT}`);
});


[2025-06-06T17:23:38.131Z] Сервер запущен на порту 3001
[2025-06-06T17:23:43.882Z] Запуск браузера Puppeteer...
[2025-06-06T17:23:47.428Z] Установка HTML-контента...
[2025-06-06T17:23:49.157Z] Вычисление высоты содержимого...
[2025-06-06T17:23:49.163Z] Высота PDF: 2348px
[2025-06-06T17:23:52.763Z] PDF успешно сгенерирован


Всё по высоте бьется.

благодаря этому костылю, height: `${scrollHeight + 1}px`, // +1px
Оно как то работает, но снизу оставляет полоску. А если убрать то снизу белая простыня, хотя в логах расчитывает высоту по html странице четко. у body, html height:100%; пробовал и auto и т.д.
  • Вопрос задан
  • 24 просмотра
Подписаться 1 Простой 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы