You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中HTML转PDF遇CSS3兼容问题,求同网页视图一致的方案

在Java中生成与网页视图完全一致的PDF方案

问题背景

项目需将包含CSS3语法的HTML内容生成PDF,先后尝试flying saucer和openhtmltoppdf库,但二者对CSS3支持不足,导致生成的PDF布局缺失、内容不完整。已尝试将外部CSS文件嵌入HTML文档,问题仍未解决。

原尝试代码

基于openhtmltoppdf的PDF生成代码

var document = Jsoup.connect(url).get();

try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
    PdfRendererBuilder builder = new PdfRendererBuilder();
    builder.withUri(uri);
    builder.toStream(outputStream);
    builder.withW3cDocument(new W3CDom().fromJsoup(document), "/");
    builder.run();

    return outputStream.toByteArray();
}

嵌入外部CSS的处理代码

for (Element link : document.select("link[rel=stylesheet]")) {
    String cssFilename = link.attr("href");

    Element style = new Element(Tag.valueOf("style"), "");
    var css = Jsoup.connect(baseUrl + cssFilename).get().body().text();

    style.appendText(css);
    link.replaceWith(style);
}

可行解决方案:基于无头Chromium的渲染

传统HTML转PDF库对现代CSS3支持有限,最可靠的方案是使用无头Chrome/Chromium渲染HTML,它完全兼容现代Web标准,生成的PDF与浏览器视图效果完全一致。

方式1:使用Selenium + Chrome Headless

  1. 添加Maven依赖
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.15.0</version>
</dependency>
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-chrome-driver</artifactId>
    <version>4.15.0</version>
</dependency>
  1. 生成PDF的代码实现
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class HtmlToPdfGenerator {
    public static byte[] generatePdfFromUrl(String url) throws Exception {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless=new");
        options.addArguments("--disable-gpu");
        options.addArguments("--no-sandbox");
        
        // 配置PDF生成参数
        options.addArguments("--print-to-pdf-no-header");
        String tempPdfPath = System.getProperty("java.io.tmpdir") + "/temp-output.pdf";
        options.addArguments("--print-to-pdf=" + tempPdfPath);

        try (ChromeDriver driver = new ChromeDriver(options)) {
            driver.get(url);
            // 等待页面完全加载(可根据页面动态内容调整等待时长)
            Thread.sleep(2000);
            // 读取生成的PDF字节数据
            return Files.readAllBytes(Paths.get(tempPdfPath));
        } finally {
            // 清理临时文件
            new File(tempPdfPath).delete();
        }
    }
}

方式2:使用Puppeteer Java封装(cdt-java-client)

这是基于Chrome DevTools Protocol的轻量化实现,无需完整Selenium环境:

  1. 添加Maven依赖
<dependency>
    <groupId>com.github.kklisura.cdt</groupId>
    <artifactId>cdt-java-client</artifactId>
    <version>1.3.0</version>
</dependency>
  1. 生成PDF的代码实现
import com.github.kklisura.cdt.launch.ChromeLauncher;
import com.github.kklisura.cdt.services.ChromeDevToolsService;
import com.github.kklisura.cdt.services.ChromeService;
import com.github.kklisura.cdt.services.types.ChromeTab;
import com.github.kklisura.cdt.protocol.commands.Page;
import java.io.ByteArrayOutputStream;

public class PuppeteerPdfGenerator {
    public static byte[] generatePdf(String url) throws Exception {
        ChromeLauncher launcher = new ChromeLauncher();
        ChromeService chromeService = launcher.launch(false, true, false);
        
        try {
            ChromeTab tab = chromeService.createTab();
            ChromeDevToolsService devToolsService = chromeService.createDevToolsService(tab);
            
            Page page = devToolsService.getPage();
            page.navigate(url);
            page.waitForLoadEvent();
            
            // 生成并读取PDF字节数据
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            page.printToPDF(false, null, null, true, null, null, null, null, null, null, null)
                .writeTo(outputStream);
            
            devToolsService.close();
            return outputStream.toByteArray();
        } finally {
            chromeService.close();
            launcher.close();
        }
    }
}

注意事项

  • 服务器环境需安装Chrome/Chromium浏览器,或使用预装浏览器的Docker镜像部署。
  • 对于动态渲染页面(如Vue/React单页应用),需增加等待时长或添加元素加载完成的判断,确保页面完全渲染后再生成PDF。
  • 可通过调整PDF生成参数(页面尺寸、边距、页眉页脚等)适配业务需求。

内容的提问来源于stack exchange,提问作者Laman Aghabayova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:20:28