安装
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.0</version>
</dependency>
创建
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.charset.Charset;
/**
* html -> pdf 工具类
*
* @author jason
*/
@Slf4j
public class Html2PdfUtil {
/**
* html -> pdf
*/
@SneakyThrows
public static void convert(String inputHtml, String outputPdf) {
// 第 1 步,创建一个 iTextSharp.text.Document 对象的实例:A4并设置边距
Document document = new Document(PageSize.A4, 10, 20, 60, 80);
// PDF属性(可写可不写)
// document.addAuthor("author");// 作者
// document.addTitle("title");// 标题
// document.addSubject("subject");// 主题
// document.addKeywords("keywords");// 关键字
// 第 2 步,为该 Document 创建一个 Writer 实例:
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdf));
writer.setPageEvent(new PdfHeaderFooter());// 页眉页脚
// 第 3 步,打开当前 Document
document.open();
// 第 4 步,为当前 Document 添加内容
// 4.1 该为加载 html 文件字符串生成pdf方式
// File file2 = ResourceUtils.getFile("D:\\test\\HelloWorld.html");
// String s = FileReader.create(file2).readString();
// ByteArrayInputStream fis = new ByteArrayInputStream(s.getBytes());
// 4.2 该为加载 html 文件生成 pdf 方式
FileInputStream fis = new FileInputStream(inputHtml);
XMLWorkerHelper.getInstance().parseXHtml(writer, document, fis, null, Charset.defaultCharset(), new CustomFontProvider());
// 第 5 步,关闭 Document
document.close();
}
}
设置字体
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import lombok.extern.slf4j.Slf4j;
/**
* 重写字体
*/
@Slf4j
public class CustomFontProvider extends XMLWorkerFontProvider {
@Override
public Font getFont(final String fontName, final String encoding,
final boolean embedded, final float size, final int style,
final BaseColor color) {
BaseFont bf = null;
try {
bf = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (Exception e) {
log.error("字体设置异常", e);
}
Font font = new Font(bf, size, style, color);
font.setColor(color);
return font;
}
}
页眉/页脚
页眉使用图片
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
/**
* 自定义页眉/页脚
*/
@Data
@Slf4j
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class PdfHeaderFooter extends PdfPageEventHelper {
private static String thomas_cook_logo;
static {
String path = PdfHeaderFooter.class.getClassLoader().getResource("").getPath().substring(1);
thomas_cook_logo = path + "/thomas_cook_logo.png";
}
/**
* 页眉-文字
*/
public String header;
/**
* 文档字体大小,页脚页眉最好和文本大小一致
*/
public int presentFontSize = 12;
/**
* 文档页面大小,最好前面传入,否则默认为A4纸张
*/
public Rectangle pageSize = PageSize.A4;
/**
* 模板
*/
public PdfTemplate total;
/**
* 基础字体对象
*/
public BaseFont bf = null;
/**
* 利用基础字体生成的字体对象,一般用于生成中文文字
*/
public Font fontDetail = null;
public PdfHeaderFooter() {
try {
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体
} catch (DocumentException | IOException e) {
log.error("字体设置异常", e);
}
}
/**
* PdfReportM1HeaderFooter
*
* @param header 页眉字符串
* @param presentFontSize 数据体字体大小
* @param pageSize 页面文档大小,A4,A5,A6横转翻转等Rectangle对象
*/
public PdfHeaderFooter(String header, int presentFontSize, Rectangle pageSize) {
this.header = header;
this.presentFontSize = presentFontSize;
this.pageSize = pageSize;
}
/**
* 文档打开时创建模板
*/
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
}
/**
* 关闭每页的时候,写入页眉/页脚
*/
@SneakyThrows
@Override
public void onEndPage(PdfWriter writer, Document document) {
// 1.写入页眉-图片
Image image = Image.getInstance(thomas_cook_logo);
image.scaleAbsolute(image.getWidth() * 2, image.getHeight() * 2);
Phrase phrase = new Phrase(header, fontDetail);
phrase.add(new Chunk(image, 0, -30));
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, phrase, (document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F, document.top() + 20, 0);
// 2.写入页脚-文字
Phrase footer1 = new Phrase("Thomas Cook", fontDetail);
Phrase footer2 = new Phrase("Geregistreerd adres: mr D.U. Stikkerstraat 10, 6842 CW Arnhem", fontDetail);
Phrase footer3 = new Phrase("BTW Nummer: NL8633474459B01", fontDetail);
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, footer1, (document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F, document.bottom() - 20, 0);
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, footer2, (document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F, document.bottom() - 40, 0);
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, footer3, (document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F, document.bottom() - 60, 0);
}
}
测试
效果如下