java - 有没有一种有效的方法可以用 Java 将多个 HTML 字符串写入 PDF 文档?

标签 java html performance itext

我正在查询 API 页面以创建该页面上信息的 PDF。 API 页面首先被解析为“TestCase”对象。 TestCase 对象中的许多字段值都是 HTML 字符串。有没有一种省时的方法将这些 HTML 字符串写入新的 PDF 文档?

我目前正在使用 iTextPDF 及其 XMLWorkerHelper 来解析 HTML 字符串并将其写入 PDF 文档。我遇到的问题是,由于我必须将很多字段编写为单独的 HTML 字符串,因此为每个 PDF 文档执行此步骤大约需要 5-6 秒,但程序的其余部分仅大约需要 3 或 4 。更糟糕的是,当我将其 Maven 项目导出为 jar 时,每个 TestCase 对象的 makePDF 步骤需要 20 秒。此步骤比其他任何步骤都要慢得多(包括从 API 查询值并将其读取到 TestCase 对象中)。我尝试收集所有 HTML 字符串并将它们放入一个大字符串中以供读取,以防问题是我正在创建 XMLWorkerHelper 的多个实例来编写由 HTML 字符串组成的 InputStream,但这并没有加快速度步。

public void makePDF(TestCase tc) throws IOException, DocumentException {
        OutputStream file = new FileOutputStream(filename);
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, file);
        document.open();
        List<FieldValue> values = tc.getFieldValues();
        for (int i = 0; i < values.size(); ++i) {
            FieldValue fv = values.get(i);
            InputStream is = new ByteArrayInputStream(fv.getValue());
            XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
            document.add(new Paragraph("\n"));
        }
        document.close();
}

我仍然需要 HTML 字符串才能正确打印到 PDF 文档,但如果可能的话,我希望缩短时间。在许多情况下,我将 20 或 30 个 TestCase 对象输入到此函数中(在某些情况下,一次多达 500 个),因此使此过程花费更少的时间运行非常重要,因为使用该工具的人不这样做不想为了制作几个 PDF 而等待 6 或 7 分钟。非常感谢任何建议。

最佳答案

您在评论中说过

Also, after running it with a test case that has none of the fields set (there are about 35 fields), where the only thing I add to the document is the field name, it still takes 20 seconds to write it all to the document.

为了测试这一点,我使用了以下代码(本质上是您的代码,其中包含及时生成的字段值,并且字段计数为常量):

int fieldCount = 35;
long start = System.nanoTime();

OutputStream file = new FileOutputStream(filename);
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
for (int i = 0; i < fieldCount; ++i) {
    InputStream is = new ByteArrayInputStream(("<p>" + "Value " + i + "</p>").getBytes());
    XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
    document.add(new Paragraph("\n"));
}
document.close();

long end = System.nanoTime();
System.out.printf("Created %s with %d fields in %f seconds.\n", filename.getName(), fieldCount, ((float)end - (float)start) / 1000000000f);

( TimingXmlWorker 测试 testMakePdfLikeEvanV )

输出:

Created MakePdfLikeEvanV.pdf with 35 fields in 3.221226 seconds.

你还说

I've tried collecting all of the HTML strings and putting them in one big string to read from in case the issue was that I was creating several instances of the XMLWorkerHelper to write the InputStream made from the HTML strings however this did not speed up that step.

我测试如下:

int fieldCount = 10000;
long start = System.nanoTime();

OutputStream file = new FileOutputStream(filename);
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
StringBuilder xmlString = new StringBuilder();
for (int i = 0; i < fieldCount; ++i) {
    xmlString.append("<p>")
             .append(("Value " + i))
             .append("</p>");
}
InputStream is = new ByteArrayInputStream(xmlString.toString().getBytes());
XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
document.close();

long end = System.nanoTime();
System.out.printf("Created %s with %d fields in %f seconds.\n", filename.getName(), fieldCount, ((float)end - (float)start) / 1000000000f);

( TimingXmlWorker 测试 testMakePdfLikeEvanVSingleWorkerCall )

输出:

Created MakePdfLikeEvanVSingleWorkerCall.pdf with 10000 fields in 1.610613 seconds.

因此,我无法重现该问题。

如果您碰巧在速度较慢的计算机上运行代码,则第一种情况(每个字段都有单独的工作人员)的差异可能是可以解释的。但在第二种情况下(所有领域只有一个工作人员),您的观察结果“没有加速”完全偏离了我的观察结果,在这种情况下,我必须大幅增加“字段”的数量才能使运行时间超过一秒。

因此,有一个您没有提及的因素正在充当中断。

  • 您是否可能存储到网络文件系统上,并且需要额外的时间进行权限检查和传输?
  • 或者是List<FieldValue> values您通过 tc.getFieldValues() 检索实际上为每个 values.size() 执行一个 Web 服务请求和values.get(i)
  • 或者是fv.getValue()执行这样的网络服务请求?
  • 或者...

关于java - 有没有一种有效的方法可以用 Java 将多个 HTML 字符串写入 PDF 文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57043863/

相关文章:

java - 如何让多个 <h :message> on a xhtml page, 显示不同的内容

java - 无法创建谷歌地图 fragment

java - apache Camel 多播 - 以异步方式执行聚合

java - 如何使用 JNI android 获取应用程序构建配置(调试或发布)?

javascript - Bootstrap 表单验证在没有控制台错误的情况下无法正常工作

javascript - 如何使用 JavaScript 获取调用者元素?

performance - MongoDB 按许多参数过滤(复合索引或不复合索引)

javascript - HTML:将表单从 http 发布到 https

jquery - 使用 jQuery 性能创建 DOM 元素

c# - .NET 集合和泛型如何工作?