如何用Playwright将Thymeleaf生成的HTML本地转为PDF(替代wkhtmltopdf)
问题描述
我有一个Spring Boot应用,原本使用已废弃的wkhtmltopdf工具,将Thymeleaf模板引擎运行时生成的HTML转换为PDF,原实现代码如下:
String html = templateEngine.process("template.html", webCtx); // 从模板引擎生成HTML内容 Pdf pdf = new Pdf(wrapperConfig); pdf.addPageFromString(html); // 将HTML模板传入解析器 byte[] result = pdf.getPDF(); // 解析HTML并返回PDF
目前该库已废弃,计划用Playwright替代,但Playwright常规用法是访问URL生成PDF,无法直接传入HTML字符串,常规实现如下:
try(Playwright playwright = Playwright.create()) { Browser browser = playwright.chromium().launch(); Page page = browser.newPage(); var url = "/some/website"; page.navigate(url); // 访问网页 page.emulateMedia(new Page.EmulateMediaOptions().setMedia(Media.SCREEN)); result = page.pdf(); // 解析网页并返回PDF }
我希望让Playwright直接解析Thymeleaf生成的HTML并渲染为PDF,不想通过Web Controller暴露URL(需处理认证,过于繁琐),请问有没有更简便的方案?比如将HTML临时存储到文件系统后让Playwright访问?
解决方案
推荐以下两种更简便的方案:
1. 直接传入HTML字符串(最优方案)
Playwright的Page对象提供了setContent()方法,可以直接传入HTML字符串进行渲染,无需依赖外部URL或文件。修改后的代码如下:
try(Playwright playwright = Playwright.create()) { Browser browser = playwright.chromium().launch(); Page page = browser.newPage(); // 直接传入Thymeleaf生成的HTML字符串 page.setContent(html); page.emulateMedia(new Page.EmulateMediaOptions().setMedia(Media.SCREEN)); byte[] result = page.pdf(); // 生成PDF }
这种方式完全不需要额外的文件或Web服务,直接复用模板引擎生成的HTML,是最简洁高效的方案。
2. 写入临时本地文件后访问(备选方案)
如果你的HTML依赖本地静态资源(如CSS、图片),直接传入字符串可能无法正确加载资源,可以将HTML写入临时文件,再通过file://协议让Playwright访问:
import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; // ... try(Playwright playwright = Playwright.create()) { Browser browser = playwright.chromium().launch(); Page page = browser.newPage(); // 创建临时HTML文件 File tempHtmlFile = File.createTempFile("template-", ".html"); Files.write(tempHtmlFile.toPath(), html.getBytes(StandardCharsets.UTF_8)); // 通过file协议访问临时文件 page.navigate("file://" + tempHtmlFile.getAbsolutePath()); page.emulateMedia(new Page.EmulateMediaOptions().setMedia(Media.SCREEN)); byte[] result = page.pdf(); // 自动清理临时文件 tempHtmlFile.deleteOnExit(); }
注意如果HTML中有相对路径的静态资源,需要确保这些资源的路径相对于临时文件的位置正确,或者将资源内容内联到HTML中(如Base64图片、内嵌CSS)。
内容的提问来源于stack exchange,提问作者Theiaz
相关产品推荐
相关产品推荐

