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

Java中含CSS3的HTML转PDF布局错乱问题求助

问题:Bootstrap5布局的HTML发票转PDF时布局错乱

我用Thymeleaf动态生成发票HTML,采用Bootstrap 5(基于CSS3)做布局,但将HTML转为PDF时,因为所用库不支持CSS3特性,导致布局完全错乱。已经尝试过flying saucer和openhtmltopdf-pdfbox,都没得到理想结果。

Thymeleaf生成的HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <meta name="viewport" content="width=device-width,
                   initial-scale=1.0"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
    <link rel="stylesheet" href="templates/css/bootstrap.min.css">
    <style media="all">
        :root {
            --primary-color: #E01B33;
        }

        .theme-background-color {
            background-color: var(--primary-color);
        }

        .theme-text-color {
            color: var(--primary-color);
        }

        tfoot {
            border-bottom: 0;
        }
    </style>
   
</head>
<body>
<div class="px-4" id="container">
    <div class="row">
        <div class="col">
            <h2 class="fw-bold">ABC</h2>
            <br/>
            <h3>asdasdsad</h3>
            <br/>
            <text>Phone Number:- asdasdasd</text>
            <br/>
            <text>Email:- sadasdasd</text>
            <br/>
            <text>Gst No.:- asdasdasdas</text>
        </div>
    </div>
    <h1 class="text-center mt-4 fw-bold theme-text-color">Sale Invoice</h1>
    <div class="row mt-4">
        <div class="col">
            <text class="fw-bold">Bill to:</text>
            <br/>
            <text class="fw-bold">asdasdasd</text>
            <br/>
            <text>asdasdasda</text>
            <br/>
            <text>Customer Number:- asdsadasd</text>
        </div>
        <div class="col text-end">
            <text class="fw-bold">Invoice No:- 1</text>
            <br/>
            <text class="fw-bold">Invoice Date:- 20/7/2022</text>
        </div>
    </div>
    <div>
        <table class="table table-striped table-hover mt-4">
            <tr class="theme-background-color">
                <th>#</th>
                <th>HSN</th>
                <th>Name</th>
                <th>Quantity</th>
                <th>Price/Unit</th>
                <th>Discount</th>
                <th>GST</th>
                <th>Amount</th>
            </tr>
            <tr>
                <td>1</td>
                <td></td>
                <td>Apple</td>
                <td>10</td>
                <td>₹ 100</td>
                <td>₹ 100(10)</td>
                <td class="text-wrap">₹ 45(GST%5)</td>
                <td>₹ 945</td>
            </tr>
            <tfoot class="border-bottom border-dark ">
            <tr>
                <td colspan="3" class="fw-bold">Total</td>
                <td colspan="3" class="fw-bold">10</td>
                <td class="fw-bold">45</td>
                <td class="fw-bold">945</td>
            </tr>
            </tfoot>
        </table>
    </div>
    <div class="row mt-4">
        <div class="col">
            <table class="table table-striped">
                <tr>
                    <td class="fw-bold text-muted">TERMS AND CONDITIONS</td>
                </tr>
                <tr>
                    <td class="fw-bold text-muted">Hello terms</td>
                </tr>
            </table>
        </div>
        <div class="col">
            <table class="table">
                <tbody>
                <tr>
                    <td>Sub Total</td>
                    <td>₹ 1,000</td>
                </tr>
                <tr class="theme-background-color">
                    <td class="fw-bold">Total</td>
                    <td class="fw-bold">₹ 945</td>
                </tr>
                <tr>
                    <td>Received</td>
                    <td>₹ 400</td>
                </tr>
                <tr>
                    <td>Balance</td>
                    <td>₹ 545</td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>

</div>

</body>
</html>

生成PDF的Java代码

public void generatePDF(FileOutputStream outputStream, String html) throws IOException {
    PdfRendererBuilder pdfBuilder = new PdfRendererBuilder();
    pdfBuilder.useFastMode();
    pdfBuilder.withUri("path/to/pdf.file");
    pdfBuilder.toStream(outputStream);
    pdfBuilder.run();
//        ITextRenderer renderer = new ITextRenderer();
//        renderer.setDocumentFromString(html);
//        renderer.layout();
//        renderer.createPDF(outputStream, false);
//        renderer.finishPDF();
}

Pom.xml依赖

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf-openpdf</artifactId>
    <version>9.1.22</version>
</dependency>
<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-core</artifactId>
    <version>1.0.10</version>
</dependency>
<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-pdfbox</artifactId>
    <version>1.0.10</version>
</dependency>
<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-java2d</artifactId>
    <version>1.0.10</version>
</dependency>

解决方案建议

  1. 替换Bootstrap版本或简化CSS

    • Bootstrap 5大量使用CSS3特性(如CSS变量、进阶flexbox),而flying saucer和openhtmltopdf对这些特性支持有限。可改用Bootstrap 3,或手动提取兼容PDF的布局样式,移除不支持的特性。
    • 直接替换CSS变量:把:root中的变量定义删除,将.theme-background-color和.theme-text-color里的变量替换为实际颜色值,避免样式失效。
  2. 修复OpenHTMLToPDF的使用逻辑

    • 当前代码中pdfBuilder.withUri("path/to/pdf.file")是错误用法,应传入HTML内容而非PDF路径。正确写法如下:
      public void generatePDF(FileOutputStream outputStream, String html) throws IOException {
          PdfRendererBuilder pdfBuilder = new PdfRendererBuilder();
          pdfBuilder.useFastMode();
          // 传入HTML内容和资源基础路径(用于加载本地CSS)
          pdfBuilder.withHtmlContent(html, "file:///your/project/templates/");
          pdfBuilder.toStream(outputStream);
          pdfBuilder.run();
      }
      
    • 确保Bootstrap CSS文件路径正确,优先使用本地资源而非CDN,避免渲染器加载外部资源失败。
  3. 调整HTML结构适配PDF渲染

    • 改用<span>或<p>替代<text>标签,因为<text>属于SVG标签,PDF渲染器处理易出问题。
    • 确保HTML符合严格XHTML规范:标签闭合、属性值用引号包裹,减少渲染器解析异常。
    • 简化表格结构,避免复杂的单元格合并和嵌套,保证PDF中表格布局稳定。
  4. 升级库版本

    • 尝试使用OpenHTMLToPDF和Flying Saucer的最新版本,新版本通常会优化CSS3特性支持,比如OpenHTMLToPDF的后续版本已部分支持CSS变量和flexbox。

内容的提问来源于stack exchange,提问作者Yash garg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 10:24:45