iTextPDF5.x版本将Html页面转成PDF,支持CSS样式,并解决中文乱码/不显示问题

2021-08-10 3532点热度 0人点赞 0条评论

看官方itextPDF的文档,推荐和DEMO都使用的是iTextPDF7的版本,但是看上去是版权或者收费的,不管怎么样,还是使用5版本比较保险。不过iText5生成PDF的方式和7是完全不同的,来看下

在pom.xml中引入itextpdf的依赖,基本上5这个大版本是定格在5.5.13.2了

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.2</version>
</dependency>

<!-- HTML转PDF需要-->
<dependency>
    <groupId>com.itextpdf.tool</groupId>
    <artifactId>xmlworker</artifactId>
    <version>5.5.13.2</version>
</dependency>

<!-- 解决中文字体乱码问题-->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

测试需要转成PDF的Html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <style>
        body {
            font-size: 14px;
        }
        * {
            margin: 0;
            padding: 0;
        }
        .mytable {border-left:#b7cee2 solid 1px;border-top:#b7cee2 solid 1px; width:100%;border-collapse:collapse;}
        .mytable  th, .mytable td{border-right:#b7cee2 solid 1px;border-bottom:#b7cee2 solid 1px;}
        .mytable  .bg_gray{background:#EEEEEE;}
        .mytable  th{text-align:center; font-size:14px; height:52px; vertical-align:middle;}
        .mytable  th small{font-size:10px; font-weight:normal;}
        .mytable  td{height:38px; vertical-align:middle; text-align:center;}
    </style>
</head>
<body>

    <div style="padding: 10px;">
        <table class="mytable">
            <tbody>
            <tr>
                <td class="bg_gray">8月9日 星期一</td>
                <td>某某功能</td>
            </tr>
            <tr>
                <td>8月9日 星期一</td>
                <td>某某功能</td>
            </tr>
            <tr>
                <td>8月10日 星期二</td>
                <td>某某功能2</td>
            </tr>
            <tr>
                <td>8月9日 星期一</td>
                <td>某某功能</td>
            </tr>
            <tr>
                <td>8月10日 星期二</td>
                <td>某某功能2</td>
            </tr>
            <tr>
                <td>8月9日 星期一</td>
                <td>某某功能</td>
            </tr>
            <tr>
                <td>8月10日 星期二</td>
                <td>某某功能2</td>
            </tr>
            <tr>
                <td>8月9日 星期一</td>
                <td>某某功能</td>
            </tr>
            <tr>
                <td>8月10日 星期二</td>
                <td>某某功能2</td>
            </tr>
            <tr>
                <td>8月9日 星期一</td>
                <td>某某功能</td>
            </tr>
            <tr>
                <td>8月10日 星期二</td>
                <td>某某功能2</td>
            </tr>
            </tbody>
        </table>
    </div>

</body>
</html>
我们准备使用的是itextPDF的xmlworker来解析html,所以是xhtml格式,要求比较严格的xml,所以需要标签要闭合,例如:<meta charset="UTF-8" > 这样写是会报错的,需要修改成:<meta charset="UTF-8" />

转换方法如下:

public static void main(String[] args) throws Exception {
    File htmlFile = new File("/Users/Terry/it/source/git/githubprojects/TestMaven/src/main/resources/sample.html");
    File pdfFile = new File("/Users/Terry/Downloads/a.pdf");
    convertHtmlToPDF(htmlFile, pdfFile);
}

/**
 * 
 * @param htmlFile 原始html文件
 * @param pdfFile 需要转成的PDF的路径
 */
private static void convertHtmlToPDF(File htmlFile, File pdfFile) throws Exception {
    Document document = new Document(); //
    PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
    document.open();

    //默认中文字体支持,防止中文乱码或者不显示
    FontProvider fontProvider = new FontProvider() {
        @Override
        public boolean isRegistered(String s) {
            return false;
        }

        private BaseFont createBaseFont(String fontDir) {
            try {
                return BaseFont.createFont(fontDir, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
            BaseFont bfChinese;
            if (style == Font.BOLD) { //如果是粗体加载粗体的字体文件
                bfChinese = createBaseFont("/Users/Terry/Downloads/font/宋体-粗体.ttf");
            } else {
                bfChinese = createBaseFont("/Users/Terry/Downloads/font/STSong.ttf");
            }
            return new Font(bfChinese, size, style, baseColor);
        }
    };
    XMLWorkerHelper worker = XMLWorkerHelper.getInstance();
    worker.parseXHtml(pdfWriter, document, new FileInputStream(htmlFile), StandardCharsets.UTF_8, fontProvider);

    document.close();
}

如上方法转成PDF,是完美支持中文、且支持内部CSS样式的。

不过你可能还有更加特殊化的需求,例如要支持外部的字体文件、支持外部的CSS文件引入。下来来看下

  • 引入外部css文件:
File cssFile = new File("/path/to/main.css");
worker.parseXHtml(pdfWriter, document, new FileInputStream(htmlFile), new FileInputStream(cssFile),StandardCharsets.UTF_8, fontProvider );
  • 引入外部font文件:
XMLWorkerFontProvider outerFontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
// yahei字体别名,在html使用,例如:<body style='font-family: yahei;'></body>
outerFontProvider.register("/path/to/微软雅黑.ttf", "yahei");

XMLWorkerHelper worker = XMLWorkerHelper.getInstance();
worker.parseXHtml(pdfWriter, document, new FileInputStream(htmlFile), StandardCharsets.UTF_8, outerFontProvider);

 

admin

这个人很懒,什么都没留下

文章评论

您需要 登录 之后才可以评论