puppeteer 生成pdf,转成图片

// server.js
const express = require('express');
const puppeteer = require('puppeteer');
const app = express();
const port = 8700;

// 中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 启动浏览器实例(单例模式)
let browser;
async function getBrowser() {
    if (!browser) {
        browser = await puppeteer.launch({
            headless: 'new',
            args: [
                '--no-sandbox',
                '--disable-setuid-sandbox',
                '--disable-dev-shm-usage',
                '--disable-gpu'
            ]
        });
    }
    return browser;
}

// 1. GET 接口 - 通过 URL 生成 PDF
app.get('/api/generate-pdf', async (req, res) => {
    try {
        const { url, filename = 'document.pdf' } = req.query;

        if (!url) {
            return res.status(400).json({ error: 'URL parameter is required' });
        }

        const browser = await getBrowser();
        const page = await browser.newPage();

        await page.goto(url, { waitUntil: 'networkidle2' });

        const pdfBuffer = await page.pdf({
            format: 'A3',
            landscape: true,
            printBackground: true,
            // margin: { top: '20mm', right: '20mm', bottom: '20mm', left: '20mm' }
        });


        await page.setViewport({
            width: 1920,
            height: 1080,
            deviceScaleFactor: 1, // 设备像素比,默认1,2为高清
        });
        await page.screenshot({path: 'screenshot.png'});
        await page.close();

        // 设置响应头
        res.set({
            'Content-Type': 'application/pdf',
            'Content-Disposition': `attachment; filename="${filename}"`,
            'Content-Length': pdfBuffer.length
        });

        res.send(pdfBuffer);

    } catch (error) {
        console.error('Error generating PDF:', error);
        res.status(500).json({ error: 'Failed to generate PDF', details: error.message });
    }
});

// 2. POST 接口 - 通过 HTML 内容生成 PDF
app.post('/api/generate-pdf-from-html', async (req, res) => {
    try {
        const { html, css, filename = 'document.pdf', options = {} } = req.body;

        if (!html) {
            return res.status(400).json({ error: 'HTML content is required' });
        }

        const browser = await getBrowser();
        const page = await browser.newPage();

        // 设置页面内容
        const fullHTML = `
      <!DOCTYPE html>
      <html>
        <head>
          <meta charset="UTF-8">
          <style>
            ${css || ''}
            @media print {
              body { -webkit-print-color-adjust: exact; }
            }
          </style>
        </head>
        <body>
          ${html}
        </body>
      </html>
    `;

        await page.setContent(fullHTML, { waitUntil: 'networkidle0' });

        const pdfOptions = {
            format: options.format || 'A4',
            printBackground: true,
            margin: options.margin || { top: '20mm', right: '20mm', bottom: '20mm', left: '20mm' },
            ...options
        };

        const pdfBuffer = await page.pdf(pdfOptions);
        await page.close();

        res.set({
            'Content-Type': 'application/pdf',
            'Content-Disposition': `attachment; filename="${filename}"`,
            'Content-Length': pdfBuffer.length
        });

        res.send(pdfBuffer);

    } catch (error) {
        console.error('Error generating PDF from HTML:', error);
        res.status(500).json({ error: 'Failed to generate PDF', details: error.message });
    }
});

// 3. 批量生成 PDF 接口
app.post('/api/generate-batch-pdfs', async (req, res) => {
    try {
        const { documents } = req.body;

        if (!Array.isArray(documents) || documents.length === 0) {
            return res.status(400).json({ error: 'Documents array is required' });
        }

        const browser = await getBrowser();
        const results = [];

        for (const doc of documents) {
            const page = await browser.newPage();

            if (doc.url) {
                await page.goto(doc.url, { waitUntil: 'networkidle2' });
            } else if (doc.html) {
                await page.setContent(doc.html, { waitUntil: 'networkidle0' });
            }

            const pdfBuffer = await page.pdf(doc.options || {});
            await page.close();

            results.push({
                filename: doc.filename || `document-${Date.now()}.pdf`,
                buffer: pdfBuffer.toString('base64'),
                size: pdfBuffer.length
            });
        }

        res.json({
            success: true,
            count: results.length,
            documents: results
        });

    } catch (error) {
        console.error('Error generating batch PDFs:', error);
        res.status(500).json({ error: 'Failed to generate PDFs', details: error.message });
    }
});

// 4. 获取 PDF 配置选项接口
app.get('/api/pdf-options', (req, res) => {
    res.json({
        formats: ['Letter', 'Legal', 'Tabloid', 'Ledger', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6'],
        margins: {
            none: { top: 0, right: 0, bottom: 0, left: 0 },
            minimal: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
            standard: { top: '20mm', right: '20mm', bottom: '20mm', left: '20mm' },
            large: { top: '40mm', right: '40mm', bottom: '40mm', left: '40mm' }
        }
    });
});

// 优雅关闭
process.on('SIGINT', async () => {
    if (browser) {
        await browser.close();
    }
    process.exit(0);
});

// 启动服务器
app.listen(port, () => {
    console.log(`PDF Generation API running at http://localhost:${port}`);
});

module.exports = app;



// const puppeteer = require('puppeteer');
//
// async function htmlToPdf() {
//    const browser = await puppeteer.launch({ headless: true });
//    const page = await browser.newPage();
//    // 加载 HTML 页面
//    await page.goto('http://127.0.0.1', { waitUntil: 'networkidle0' });
//    // 生成 PDF
//    await page.pdf({
//        path: 'output.pdf', // 保存路径
//        format: 'A4', // 页面格式
//        printBackground: true, // 打印背景样式
//    });
//    await browser.close();
//    console.log('PDF 已生成');
// }
// htmlToPdf();

转成图片效果更好

posted @ 2026-01-20 11:25  liliyou  阅读(0)  评论(0)    收藏  举报