JAVA实现HTML转PDF的五种方法详解

在Java开发中,将HTML内容转换为PDF格式是常见的业务需求,尤其在生成报表、电子合同、在线文档等场景中。由于HTML与PDF在渲染机制上的差异,转换过程需要处理样式兼容性、字体嵌入、布局分页等复杂问题。本文ZHANID工具网将系统梳理五种主流的Java实现方案,通过技术原理、代码示例和注意事项的对比分析,为开发者提供可落地的技术选型参考。

一、基于wkhtmltopdf的命令行转换

技术原理:wkhtmltopdf是一个开源工具,通过集成WebKit渲染引擎将HTML转换为PDF。其核心优势在于高保真渲染,能准确还原现代HTML5和CSS3的视觉效果,尤其适合复杂页面布局的转换。

实现步骤

  1. 环境配置:下载对应操作系统的二进制包,配置系统环境变量或指定绝对路径。

    #Linux示例安装命令
    wgethttps://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
    sudodpkg-iwkhtmltox_0.12.6-1.focal_amd64.deb
  2. Java调用封装:通过Runtime.exec()执行系统命令,需处理进程流以避免阻塞。

    publicclassWkhtmlToPdfConverter{
    privatestaticfinalStringTOOL_PATH="/usr/local/bin/wkhtmltopdf";
    
    publicstaticbooleanconvert(StringhtmlPath,StringpdfPath){
    ProcessBuilderpb=newProcessBuilder(
    TOOL_PATH,
    "--margin-top","20mm",
    "--header-html","header.html",//可选页眉
    htmlPath,
    pdfPath
    );
    try{
    Processprocess=pb.start();
    //异步读取错误流防止阻塞
    newThread(()->{
    try(BufferedReadererrorReader=newBufferedReader(
    newInputStreamReader(process.getErrorStream()))){
    Stringline;
    while((line=errorReader.readLine())!=null){
    System.err.println("[WKHTMLError]"+line);
    }
    }catch(IOExceptione){
    e.printStackTrace();
    }
    }).start();
    returnprocess.waitFor()==0;
    }catch(IOException|InterruptedExceptione){
    e.printStackTrace();
    returnfalse;
    }
    }
    }

关键注意事项

  • 字体兼容性:需确保系统安装了PDF所需的字体(如中文字体),可通过--user-style-sheet参数指定CSS覆盖默认样式。

  • 性能瓶颈:每个转换请求都会启动新进程,高并发场景下建议使用连接池管理进程

  • 跨平台问题:Windows路径需转义反斜杠,Linux需处理权限问题。

二、iText 7 + html2pdf扩展库

技术原理:iText是商业级PDF生成库,其html2pdf扩展通过解析HTML DOM树并映射到PDF元素,支持CSS2.1标准和部分CSS3属性(如圆角、阴影)。

实现步骤

  1. 依赖配置(Maven):

    com.itextpdf
    html2pdf
    5.0.4
    
    
    com.itextpdf
    font-asian
    7.2.5
    
  2. 核心转换代码

    publicclassITextHtmlToPdf{
    publicstaticvoidconvert(StringhtmlPath,StringpdfPath)throwsIOException{
    try(PdfWriterwriter=newPdfWriter(pdfPath);
    PdfDocumentpdf=newPdfDocument(writer)){
    ConverterPropertiesproperties=newConverterProperties();
    //设置中文字体
    FontProviderfontProvider=newDefaultFontProvider(false,false,false);
    fontProvider.addFont("simsun.ttc");//宋体
    properties.setFontProvider(fontProvider);
    
    //执行转换
    HtmlConverter.convertToPdf(newFileInputStream(htmlPath),pdf,properties);
    }
    }
    }

关键优化点

  • 分页控制:通过CSS的page-break-after属性实现强制分页。

  • 表格处理:复杂表格需使用

    并显式设置列宽。
  • 性能优化:对于大文件,启用setSplitLate(false)避免内存溢出。

  • 三、Flying Saucer(XHTMLRenderer)

    技术原理:基于iText的开源项目,通过XHTML+CSS 2.1渲染生成PDF,适合需要完全控制样式的场景。

    实现步骤

    1. 依赖引入

      org.xhtmlrenderer
      flying-saucer-pdf
      9.1.22
      
    2. 转换实现

      publicclassFlyingSaucerConverter{
      publicstaticvoidconvert(Stringhtml,StringpdfPath)throwsException{
      StringoutputFile=pdfPath;
      OutputStreamos=newFileOutputStream(outputFile);
      ITextRendererrenderer=newITextRenderer();
      
      //字体配置
      ITextFontResolverfontResolver=renderer.getFontResolver();
      fontResolver.addFont("simsun.ttc",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
      
      //设置XHTML内容(需符合XML规范)
      renderer.setDocumentFromString(html);
      renderer.layout();
      renderer.createPDF(os);
      os.close();
      }
      }

    常见问题解决

    • HTML合法性:必须为格式良好的XHTML(如标签闭合、属性引号),可使用Jsoup预处理:

      StringcleanHtml=Jsoup.parse(rawHtml).html();
    • 图片处理:相对路径需通过setBaseURL()指定基准目录。

    四、PD4ML(商业库)

    技术原理:专为HTML转PDF设计的商业库,支持JavaScript渲染动态内容,适合复杂Web应用。

    核心特性

    • 动态表单支持:可交互的PDF表单字段

    • 条形码生成:内置Code128/QRCode支持

    • 高级布局:精确控制页眉页脚、水印、批注

    代码示例

    publicclassPd4mlConverter{
    publicstaticvoidconvert(StringhtmlPath,StringpdfPath)throwsException{
    PD4MLpd4ml=newPD4ML();
    pd4ml.setPageSize(PD4Constants.A4);
    pd4ml.setHtmlWidth(960);
    pd4ml.useTTF("fonts",true);//字体目录
    pd4ml.setDefaultTTFs("SimSun","SimSun","SimSun");//中文字体
    
    try(FileOutputStreamfos=newFileOutputStream(pdfPath)){
    pd4ml.render("file://"+newFile(htmlPath).getAbsolutePath(),fos);
    }
    }
    }

    授权说明:PD4ML采用按域名授权模式,开发环境可申请免费试用许可。

    五、OpenHTMLToPDF(Flying Saucer分支)

    技术原理:Flying Saucer的现代分支,支持CSS3 Flexbox部分Grid布局,适合响应式设计转换。

    优势对比

    特性 Flying Saucer OpenHTMLToPDF
    CSS Flexbox支持
    字体子集嵌入
    Java模块化支持

    实现代码

    publicclassOpenHtmlConverter{
    publicstaticvoidconvert(Stringhtml,StringpdfPath)throwsException{
    try(OutputStreamos=newFileOutputStream(pdfPath)){
    PdfRendererBuilderbuilder=newPdfRendererBuilder();
    builder.withFile(newFile(html));//或使用withHtmlContent()
    builder.useFastMode();//性能优化
    builder.toStream(os);
    builder.run();
    }
    }
    }

    综合对比与选型建议

    方案 适用场景 复杂度 性能 成本
    wkhtmltopdf 高保真复杂页面 免费
    iText 7 企业级文档生成 中高 商业
    Flying Saucer 精确样式控制的静态页面 中高 免费
    PD4ML 动态内容/表单密集型应用 商业
    OpenHTMLToPDF 现代CSS布局的响应式页面 中高 免费

    推荐实践

    1. 简单需求:优先选择OpenHTMLToPDF或Flying Saucer

    2. 企业级应用:iText 7(需购买商业授权)或PD4ML

    3. 高并发场景:wkhtmltopdf需配合进程池管理

    4. 中文支持:所有方案均需显式配置中文字体文件

    常见问题解决方案

    1. 中文乱码

    • 确保HTML使用UTF-8编码

    • 在PDF生成代码中显式注册中文字体

    • 示例(iText):

      FontProviderfontProvider=newDefaultFontProvider(false,false,false);
      fontProvider.addFont("NotoSansCJKsc-Regular.otf");//思源黑体
      properties.setFontProvider(fontProvider);
  • 表格跨页断裂

    /*禁止表格跨页*/
    table{page-break-inside:avoid;}
    /*或指定最小行高*/
    tr{min-height:20mm;}
  • 背景色丢失

    • 避免使用CSS渐变,改用纯色

    • 确保设置了背景色:

      body{background-color:#ffffff;}
  • 图片不显示

    • 使用绝对路径或base64编码内嵌图片

    • 检查图片权限(特别是网络图片需处理SSL证书)

    结语

    HTML转PDF的技术选型需综合考虑渲染质量开发成本维护复杂度。对于大多数业务场景,iText 7或OpenHTMLToPDF可提供良好的平衡点;当遇到特殊需求(如动态表单、复杂交互)时,PD4ML的商业支持能显著降低开发风险。建议在实际项目中通过POC验证确定最终方案,并建立完善的测试用例库覆盖各种边界情况。

发布于 2025-09-13 02:45:14
分享
海报
139
上一篇:MySQL创建和删除索引命令CREATE/DROP INDEX使用方法详解 已经没有更多啦
目录

    忘记密码?

    图形验证码