为 iText 预处理 HTML CSS JS
Preprocessing HTML CSS JS for iText
我正在尝试使用嵌入在 Java 代码中的 iText 将使用 HTML/CSS/JS 构建的网页转换为 PDF。然而,iText 告诉我们,虽然 pdfHTML 支持 CSS,但它不支持 JS。他们建议使用预处理器 "run" 页面中的 Java 脚本并取回原始 HTML.
没有 Java 脚本,iText 可以很好地生成 PDF。但是,我们需要能够将来自服务调用的数据注入 HTML。我用 JQuery 来完成这个。我们也在调用和使用 FusionCharts API 来渲染一些图表。这些在生成 PDF 之前也有效。
有人知道这样的事情吗?它也需要能够从我们的 Java 后端调用。
谢谢!
在HTML + CSS + JS页面上有几种评估JS代码的方法。为此,我们需要浏览器的模拟(或浏览器本身),因为使用 DOM 操作评估 JS 正是浏览器在呈现页面之前必须做的事情。
选项 1
使用 HtmlUnit - “Java 程序的无 GUI 浏览器”。
首先,我们需要添加依赖项(例如通过 Maven):
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.32</version>
</dependency>
然后,打开页面,等待JS完成它的工作,并将页面源码提供给iText pdfHTML:
WebClient webClient = new WebClient();
// You might need this configuration if HtmlUnit fails without it
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.waitForBackgroundJavaScript(10 * 1000);
HtmlPage page = webClient.getPage(url);
String xml = page.asXml();
ConverterProperties properties = new ConverterProperties().setBaseUri(url);
HtmlConverter.convertToPdf(source, new PdfWriter("result.pdf"), properties);
HtmlUnit 不完全支持 JS,因此在评估 JS 代码时可能会抛出错误。因此,您可能想要抑制它们(我已将此配置和关于它的注释添加到代码示例中)。当然,您的结果可能看起来不正确。但这是纯粹的 Java 解决方案。
选项 2
向我们每天使用的现实世界浏览器寻求帮助
我们日常使用的浏览器(Chrome、Firefox、Safari等)对JS评估的支持最好。您可以使用例如浏览器引擎Selenium web automation tool. What we will be doing is opening a page in a browser, waiting until page loads and then using the source for HTML -> PDF conversion. My example will be for Chrome, but you can do it in a similar way for other browsers. First, you will need to download 一个 Chrome 驱动程序并将其解压缩到您系统的某个位置。
然后添加如下Maven依赖:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.14.0</version>
</dependency>
现在我们要写一些代码,类似于第一个选项:
System.setProperty("webdriver.chrome.driver", "C:\path\to\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
driver.get(url);
new WebDriverWait(driver, 20).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
String source = driver.getPageSource();
driver.close();
ConverterProperties properties = new ConverterProperties().setBaseUri(url);
HtmlConverter.convertToPdf(source, new PdfWriter("result.pdf"), properties);
这个选项可能会有点慢,并且有更多的先决条件(浏览器、驱动程序),但它保证了防弹 JS 支持。
我正在尝试使用嵌入在 Java 代码中的 iText 将使用 HTML/CSS/JS 构建的网页转换为 PDF。然而,iText 告诉我们,虽然 pdfHTML 支持 CSS,但它不支持 JS。他们建议使用预处理器 "run" 页面中的 Java 脚本并取回原始 HTML.
没有 Java 脚本,iText 可以很好地生成 PDF。但是,我们需要能够将来自服务调用的数据注入 HTML。我用 JQuery 来完成这个。我们也在调用和使用 FusionCharts API 来渲染一些图表。这些在生成 PDF 之前也有效。
有人知道这样的事情吗?它也需要能够从我们的 Java 后端调用。
谢谢!
在HTML + CSS + JS页面上有几种评估JS代码的方法。为此,我们需要浏览器的模拟(或浏览器本身),因为使用 DOM 操作评估 JS 正是浏览器在呈现页面之前必须做的事情。
选项 1
使用 HtmlUnit - “Java 程序的无 GUI 浏览器”。
首先,我们需要添加依赖项(例如通过 Maven):
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.32</version>
</dependency>
然后,打开页面,等待JS完成它的工作,并将页面源码提供给iText pdfHTML:
WebClient webClient = new WebClient();
// You might need this configuration if HtmlUnit fails without it
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.waitForBackgroundJavaScript(10 * 1000);
HtmlPage page = webClient.getPage(url);
String xml = page.asXml();
ConverterProperties properties = new ConverterProperties().setBaseUri(url);
HtmlConverter.convertToPdf(source, new PdfWriter("result.pdf"), properties);
HtmlUnit 不完全支持 JS,因此在评估 JS 代码时可能会抛出错误。因此,您可能想要抑制它们(我已将此配置和关于它的注释添加到代码示例中)。当然,您的结果可能看起来不正确。但这是纯粹的 Java 解决方案。
选项 2
向我们每天使用的现实世界浏览器寻求帮助
我们日常使用的浏览器(Chrome、Firefox、Safari等)对JS评估的支持最好。您可以使用例如浏览器引擎Selenium web automation tool. What we will be doing is opening a page in a browser, waiting until page loads and then using the source for HTML -> PDF conversion. My example will be for Chrome, but you can do it in a similar way for other browsers. First, you will need to download 一个 Chrome 驱动程序并将其解压缩到您系统的某个位置。
然后添加如下Maven依赖:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.14.0</version>
</dependency>
现在我们要写一些代码,类似于第一个选项:
System.setProperty("webdriver.chrome.driver", "C:\path\to\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
driver.get(url);
new WebDriverWait(driver, 20).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
String source = driver.getPageSource();
driver.close();
ConverterProperties properties = new ConverterProperties().setBaseUri(url);
HtmlConverter.convertToPdf(source, new PdfWriter("result.pdf"), properties);
这个选项可能会有点慢,并且有更多的先决条件(浏览器、驱动程序),但它保证了防弹 JS 支持。