java使用flying-saucer-pdf-itext5进行html转pdf

    关于jar包
   <dependency>
      <groupId>org.xhtmlrenderer</groupId>
      <artifactId>flying-saucer-pdf-itext5</artifactId>
      <version>9.1.18</version>
  </dependency>

如果只是html通过url或字符串来转换成pdf的话,只需要上面一个jar足矣。有时候项目比较庞大引入的jar比较多的时候,可能会跟别的jar起冲突,我就遇到过flying-saucer-pdf-itext5的9.1.0及以上的版本出现jar冲突而9.1.0以下的版本不会冲突的情况,如果冲突了就得指定特定的路径,比如:

    System.setProperty("javax.xml.transform.TransformerFactory", 
    "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
    System.setProperty("javax.xml.parsers.DocumentBuilderFactory", 
    "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
  • 关于中文不换行的问题
    在flying-saucer-pdf-itext5的9.0.6及以下版本,中文是不会换行的,在网上说需要程序自己拼接\n或者修改源码org.xhtmlrenderer.layout.Breaker.java。但其实,在flying-saucer-pdf-itext5的9.0.7及以上版本就已经支持中文换行了,不需要这么麻烦自己造轮子。

  • 关于中文字体问题
    使用itext转pdf是需要安装中文字体库的,不然中文显示不出来,在itext里面有多种引入字体的方式,其中html通过字符串转pdf的,使用以下方式引入字体库。并且在前端样式中加入font-family:SimSun;,即可显示中文。如果是linux系统中,可以路径改成/usr/share/fonts/chinese/simsun.ttc(linux中默认是没有字体库的哦,需要自己安装)。

      String path = "c:/Windows/Fonts/simsun.ttc";
      ITextFontResolver fontResolver = renderer.getFontResolver();
      fontResolver.addFont(path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
    其实纸张大小和换行其中一个方式可以用样式来指定纸张大小和换页的。
    比如指定纸张大小为a4横向排版、并且边距为0的样式:
    @page{size:297mm 210mm;margin:0;padding:0;margin:0}
    换页样式:.pageNext{page-break-after:always;}
    在需要换行的位置加入前端代码<div class='pageNext'></div>,即可换页。

  • 关于引入的css样式是否需要加绝对路径问题
    很多时候,前端的样式引入是可能用相对路径的,但pdf转换的时候是必须用绝对路径的,那就要么让前端把根路径加上,又或者我们在程序里面把link标签拎出来遍历给它们加上根路径,但其实还有一种方式,也就是flying-saucer-pdf提供的一个方法renderer.setDocumentFromString(html,baseUrl)也是能达到效果,不需要我们事先加好根路径。

  • 关于样式失效问题
    样式在浏览器看起来可能正常,但转成pdf的时候可能失效。这时候可能是该插件不支持这种样式,也可能是该页面多个样式冲突了。

  • 该转换方式的html必须是静态化的,该转换方式对html的检查非常严格,必须使用闭合的标签,否则报错。

  • 完整的代码实现方式:

  • package itext.html2pdf;
    import com.itextpdf.text.DocumentException;
    import com.itextpdf.text.pdf.BaseFont;
    import org.xhtmlrenderer.pdf.ITextFontResolver;
    import org.xhtmlrenderer.pdf.ITextRenderer;
    import java.io.File;
    import java.io.IOException;
    import java.io.OutputStream;
    public class PDFUtil {
    * 通过html的字符串转pdf
    * @param out
    * @param html
    * @throws IOException
    * @throws DocumentException
    public static void createPdfByHtml(OutputStream out, String html) throws IOException, DocumentException {
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);
        // 解决中文支持问题
        ITextFontResolver fontResolver = renderer.getFontResolver();
        fontResolver.addFont("c:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        renderer.layout();
        renderer.createPDF(out);
    * 通过html的文件路径转pdf
    * @param out
    * @param htmlFilePath
    * @throws IOException
    * @throws DocumentException
    public static void createPdfByUrl(OutputStream out,String htmlFilePath) throws IOException, DocumentException{
        ITextRenderer renderer = new ITextRenderer();
        String url = new File(htmlFilePath).toURI().toURL().toString();
        renderer.setDocument(url);
        // 解决中文支持问题
        ITextFontResolver fontResolver = renderer.getFontResolver();
        fontResolver.addFont("c:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        //解决图片的相对路径问题
        //renderer.getSharedContext().setBaseURL("http://localhost:8080");//file:/e:/