关于HTML页面转pdf的一点经验

前言

目前好多报表及样式打印都有需要pdf格式,但是人们又习惯了html画页面,当然这是由于本身PDF去画页面样式是有一定难度的,若是你特别精通PDF,当我没说。那么有没有什么工具可以直接将html页面直接转换成pdf呢,当然是有的,目前我已知的有两种,jasper 和iitextpdf,该文,仅介绍itextpdf转pdf遇到的一些坑。

正文

### 一
jar
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>html2pdf</artifactId>
        <version>5.0.2</version>
    </dependency>

转换代码

package com.zf;

import com.itextpdf.html2pdf.HtmlConverter;

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws Exception {
        String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
        String htmlFile = baseDir+"test.html";
        String pdfFile = baseDir+"test.pdf";
        HtmlConverter.convertToPdf(new File(htmlFile),new File(pdfFile));
    }
}

html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>dhakdhaksda</div>
    <div>你好我好大家好</div>
</body>
</html>

pdf页面
在这里插入图片描述
这时,大家会发现中文丢失,这是itextpdf 工具html转pdf 的第一个通用问题。这个问题很好解决,引入字体设置就可以了。上代码
###二
jar 包

   <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>html2pdf</artifactId>
        <version>5.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext-asian</artifactId>
        <version>5.2.0</version>
    </dependency>

添加字体(记得添加ttf的,ttc的需要设置什么,不然不会识别)

    public static void main(String[] args) throws Exception {
        String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
        String htmlFile = baseDir+"test.html";
        String pdfFile = baseDir+"test1.pdf";
        String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
        ConverterProperties converterProperties = new ConverterProperties();
        FontProvider fontProvider = new FontProvider();
        fontProvider.addFont(fontPath);
        converterProperties.setFontProvider(fontProvider);
        HtmlConverter.convertToPdf(new File(htmlFile),new File(pdfFile),converterProperties);
    }

结果
在这里插入图片描述
简单的模板样式都可以这样转换,但是如果有复杂的html页面,这样转换你会发现,好多html标签及css样式不生效。
故这里展示第二种itext htnl转pdf 的方法

jar

    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.13.3</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf.tool</groupId>
        <artifactId>xmlworker</artifactId>
        <version>5.5.13.3</version>
    </dependency>
    public static void main(String[] args) throws Exception {
        String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
        String htmlFile = baseDir+"test.html";
        String pdfFile = baseDir+"test3.pdf";
        String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
        Document document = new Document();//这里可以设置纸张大小
        PdfWriter instance1 = PdfWriter.getInstance(document, new FileOutputStream(new File(pdfFile)));
        document.open();
        //当然这里也要设置字体,不然中文无法显示
        FontProvider fontProvider = new FontProvider(){

            @Override
            public boolean isRegistered(String s) {
                return false;
            }
            private BaseFont createFont(){
                try{
                    return BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
                }catch(Exception ex){
                    ex.printStackTrace();
                }
                return null;
            }
            @Override
            public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
                return new Font(createFont(),v,i,baseColor);
            }
        };
        XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
        instance.parseXHtml(instance1,document,new FileInputStream(new File(htmlFile)), StandardCharsets.UTF_8,fontProvider);
        document.close();
    }

注意点:
1注意标签一定要闭合,不然

Exception in thread "main" com.itextpdf.tool.xml.exceptions.RuntimeWorkerException: Invalid nested tag head found, expected closing tag meta.

结果:
在这里插入图片描述
2注意table 标签中一定要有tr td 不然

Exception in thread "main" java.lang.IllegalArgumentException: The number of columns in PdfPTable constructor must be greater than zero.

3 如果像设置背景图片,在html 设置是不在pdf转换过程中生效的,可以换种方式。

    public static void main(String[] args) throws Exception {
        String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
        String htmlFile = baseDir+"test.html";
        String pdfFile = baseDir+"test4.pdf";
        String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
        String imagePath = baseDir+"aa.png";
        Document document = new Document();//这里可以设置纸张大小
        PdfWriter instance1 = PdfWriter.getInstance(document, new FileOutputStream(new File(pdfFile)));
        document.open();
        Image image =  Image.getInstance(imagePath);
        image.setAbsolutePosition(0,0);
        image.scaleAbsolute(595,842);
        document.add(image);
        //当然这里也要设置字体,不然中文无法显示
        FontProvider fontProvider = new FontProvider(){

            @Override
            public boolean isRegistered(String s) {
                return false;
            }
            private BaseFont createFont(){
                try{
                    return BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
                }catch(Exception ex){
                    ex.printStackTrace();
                }
                return null;
            }
            @Override
            public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
                return new Font(createFont(),v,i,baseColor);
            }
        };
        XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
        instance.parseXHtml(instance1,document,new FileInputStream(new File(htmlFile)), StandardCharsets.UTF_8,fontProvider);
        document.close();
    }

记得html页面body 透明度设置为0 即opacity: 0;
当然这样设置背景还有一个弊端,就是pdf有多页,这个只显示一页。若要设置多页,需在监听事件中设置背景图片,代码如下:

package com.zf;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfIndirectReference;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class Test {
    public static void main(String[] args) throws Exception {
        String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
        String htmlFile = baseDir+"test.html";
        String pdfFile = baseDir+"test4.pdf";
        String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
        String imagePath = baseDir+"aa.png";
        Document document = new Document();//这里可以设置纸张大小
        PdfWriter instance1 = PdfWriter.getInstance(document, new FileOutputStream(new File(pdfFile)));
        document.open();
        instance1.setPageEvent(new BackAdd());
        //当然这里也要设置字体,不然中文无法显示
        FontProvider fontProvider = new FontProvider(){

            @Override
            public boolean isRegistered(String s) {
                return false;
            }
            private BaseFont createFont(){
                try{
                    return BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
                }catch(Exception ex){
                    ex.printStackTrace();
                }
                return null;
            }
            @Override
            public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
                return new Font(createFont(),v,i,baseColor);
            }
        };
        XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
        instance.parseXHtml(instance1,document,new FileInputStream(new File(htmlFile)), StandardCharsets.UTF_8,fontProvider);
        document.close();
    }
    
}
class BackAdd extends PdfPageEventHelper{
    public void onCloseDocument(PdfWriter writer, Document document) {
        String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
        String imagePath = baseDir+"aa.png";
        Image image = null;
        try {
            image = Image.getInstance(imagePath);
            image.setAbsolutePosition(0,0);
            image.scaleAbsolute(595,842);
            document.add(image);
        } catch (BadElementException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值