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>
解决方案建议
替换Bootstrap版本或简化CSS
- Bootstrap 5大量使用CSS3特性(如CSS变量、进阶flexbox),而flying saucer和openhtmltopdf对这些特性支持有限。可改用Bootstrap 3,或手动提取兼容PDF的布局样式,移除不支持的特性。
- 直接替换CSS变量:把
:root中的变量定义删除,将.theme-background-color和.theme-text-color里的变量替换为实际颜色值,避免样式失效。
修复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,避免渲染器加载外部资源失败。
- 当前代码中
调整HTML结构适配PDF渲染
- 改用
<span>或<p>替代<text>标签,因为<text>属于SVG标签,PDF渲染器处理易出问题。 - 确保HTML符合严格XHTML规范:标签闭合、属性值用引号包裹,减少渲染器解析异常。
- 简化表格结构,避免复杂的单元格合并和嵌套,保证PDF中表格布局稳定。
- 改用
升级库版本
- 尝试使用OpenHTMLToPDF和Flying Saucer的最新版本,新版本通常会优化CSS3特性支持,比如OpenHTMLToPDF的后续版本已部分支持CSS变量和flexbox。
内容的提问来源于stack exchange,提问作者Yash garg
相关产品推荐
相关产品推荐

