首页 > 解决方案 > 有没有一种有效的方法可以将多个 HTML 字符串写入 Java 中的 PDF 文档?

问题描述

我正在查询 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 对象中)。一世'

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 分钟。非常感谢任何建议。

标签: javahtmlperformanceitext

解决方案


在你说的评论中

此外,在使用未设置任何字段(大约有 35 个字段)的测试用例运行它之后,我添加到文档中的唯一内容是字段名称,仍然需要 20 秒才能将其全部写入文档.

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

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.

此外你说

我尝试收集所有 HTML 字符串并将它们放在一个大字符串中以供读取,以防问题是我正在创建 XMLWorkerHelper 的多个实例来编写由 HTML 字符串制成的 InputStream 但这并没有加快速度步。

我对此进行了如下测试:

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.

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

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

因此,有一个你没有提到的因素是休息。

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

推荐阅读