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

时间:2019-07-15 16:31:16

标签: 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个),因此使此过程耗时更少是非常重要的,因为使用该工具的人不会只想等待6或7分钟即可制作几张PDF。任何建议都将不胜感激。

1 个答案:

答案 0 :(得分:0)

在您所说的评论中

  

此外,在使用没有设置任何字段的测试用例(大约有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.

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

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

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

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