【问题标题】:How to decrease the time taken by html-pdf for report generation?如何减少 html-pdf 生成报告的时间?
【发布时间】:2019-06-08 07:24:52
【问题描述】:

我正在处理大量数据。我想生成一个包含 1 年数据的 PDF 报告。我正在使用 html-pdf 来做到这一点。问题是生成 PDF 大约需要 20 分钟。可以减吗?

我不想让我的用户等待 20 分钟。

注意:我只想在服务器端生成 PDF,我想把它邮寄给用户。

我尝试了一些解决方案,但我不喜欢任何解决方案。但我观察到,当我从 google 下载一些文件时,工作流程非常流畅。

我想知道如何让我的工作流程顺畅

 app.post('/api', (req, res) => {
    var json = req.body;
    var sqlGet = 'SELECT StationId,TimeStamp,data->>"$.temperature" as temperature,data->"$.humidity" as humidity,data->"$.so2" as so2,data->"$.no2" as no2,data->"$.co" as co,data->"$.o3" as o3,data->"$.co2" as co2,data->"$.pm10" as pm10,data->"$.noise" as noise,data->"$.rain" as rain,data->"$.wdir" as wdir,data->"$.wspeed" as wspeed,data->"$.press" as press FROM TwentyStationFiveYearData WHERE StationId = ' + json.stationid + ' AND TimeStamp >= ' + json.start + ' AND TimeStamp <= ' + json.end;
    console.log('' + sqlGet);
    connection.query(sqlGet, function(err, result) {
        if (err) {
            console.log('error' + err);
        } else {
            var htmlCode = generateTable(result, 15);
            //var output = fs.createWriteStream('reports/' + json.start + '-' + json.end + '.pdf');
            pdf.create(htmlCode, {
                orientation: 'landscape',
                type: 'pdf',
                timeout: '1800000'
            }).toStream(function(err, stream) {
                if (err) {
                    console.log('stream did not work ' + err);
                } else {
                    stream.pipe(fs.createWriteStream('output.pdf'));
                    console.log('pdf generated');
                    res.send("report will be mailed");
                }
            });
        }
    });
});

function generateTable(jsonData, columns) {
    var tab = '';
    var headers = ['StationId', 'TimeStamp', 'temperature', 'humidity', 'so2', 'no2', 'co', 'o3', 'co2', 'pm10', 'noise', 'rain', 'wdir', 'wspeed', 'press'];
    tab += '<tr>';

    for (var c = 0; c < columns; c++) {
        tab += '<th>';
        tab += headers[c];
        tab += '</th>';
    }
    tab += '<tr>';
    jsonData.forEach(obj => {
        tab += '<tr>';
        for (var c = 0; c < columns; c++) {
            tab += '<td>';
            tab += obj[headers[c]];
            tab += '</td>';
        }
        tab += '</tr>';
    });
    tab = '<table border = "1">' + tab + '</table>';
    return html(tab);
}

function html(table) {
    var htmlCode = '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>Title</title></head><body>' + table + '</body></html>';
    return htmlCode;

}

我想让我的工作流程更顺畅并减少生成 PDF 报告所需的时间

【问题讨论】:

  • 您在 (StationId,TimeStamp) 上有一个复合索引?
  • 是的,我已经对 stationid、timestamp、stationid 和 timestamp 进行了索引。这些是我拥有的 3 种索引
  • 你应该有一个关于 station_id,timestamp 的复合索引。您还可以在时间戳上有一个单独的索引。单独的 station_id 索引是多余的
  • 现在,这不是问题。我使用 stationid 和 timestamp 参数进行查询,这意味着它将使用 stationid 和时间戳索引。
  • 我想知道任何减少 pdf 生成时间的建议

标签: node.js phantomjs html-pdf phantomjs-node


【解决方案1】:

您是否缩小了耗时的操作范围?是不是pdf渲染最耗时?

我要做的是检查原始查询以查看执行所需的时间。

其次,我会检查结果的大小,如果它可以以某种方式压缩,最后,我会检查 PDF 渲染。

我在 PHP 中使用了 dompdf,当我渲染 png 而不是 jpg 时出现了性能问题,但我认为情况并非如此,因为我没有看到任何图像渲染。

因此,如果您可以灵活地使用另一个库,您最好这样做,或者检查您使用的库中的性能调整。

我想字体渲染可能需要很长时间。

希望我能给你一些提示!

【讨论】:

    【解决方案2】:

    npm's html-pdf 使用 phantomjs 。当您使用它时,它会在子进程中创建一个无显示的 Web 浏览器实例,然后使用它来呈现您提供给它的 html 数据,然后使用相同的实例将其打印到 pdf 文件中。这样可行。但是正如你所发现的,当你给它一个大的 html 对象时它会很慢。

    不过,20 分钟还是很长的时间。您的机器是否可能受到 RAM 限制? phantomjs 子进程是否耗尽 RAM 并抖动?

    也许pdf-puppeteer 更快。值得一试,而且它比依赖 now-deprecated phantomjs 更具前瞻性。

    你可以试试PDFKit。它直接从您的节点程序中生成 pdf 文件。 这会更快,因为它不需要子进程。但是,您必须重新编写报表程序,以便它使用 PDFKit 的 API 而不是浏览器实例。

    有多种可用的软件即服务解决方案类似于html-pdf,但速度更快。您可以考虑使用其中之一,尤其是在快速交付 pdf 文件对您的业务至关重要的情况下。

    最后,即使您不想这样做,您也可以编写 HTML 和 CSS,这样它就可以很好地进行打印格式化。并要求您的用户打印。

    【讨论】:

    • 我需要 PDFKit 中不存在的输出 pdf 中的表格。所以我不能使用它。我会试试 pdf-puppeteer..
    【解决方案3】:

    pdf.create(htmlCode, { 方向:'风景', 类型:'pdf', 超时:'1800000'

    您已将超时设置为 1800000 毫秒,因此生成 pdf 需要很长时间。所以

    var 选项 = { 格式:“A3”, 方向:“风景”, 边框:“10mm”, 超时:“3000” };

    var document = {
        type: 'buffer',
        template: html,
        context: {
            Wellsfargo: wellsfargo
        },
    };
    
    
    if (document === null) {
        return null;
    
    } else {
        pdf.create(document, options).then(response => {
            res.writeHead(200, {
                "Content-Disposition": "attachment;filename=" + "wellsFargo.pdf",
                'Content-Type': 'application/pdf'
            });
            return res.end(response);
        })
        .catch(error => {
            console.error(error);
            return res.status(200).type('application/pdf').send(error.toString());
        });
    };
    

    });

    尝试这些超时或删除超时..

    因为 phanthomjs 默认超时是 3000 毫秒。

    使用dynamic-html-pdf包它非常快..

    https://www.npmjs.com/package/dynamic-html-pdf

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 2020-07-22
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    相关资源
    最近更新 更多