这次总结一下转pdf,可以设置页眉页脚,水印等
按照之前发过一次转pdf的思路,先是写好html模板,然后用freemarMker填数据得到html的字符串,然后用itext转成pdf,这次主要是添加了页眉页脚的新功能,这里参考了https://blog.youkuaiyun.com/FYWT98/article/details/52189029。
新建了一个项目把架包和代码都放在了一起,方便自己以后,需要的可以评论找我发,一套
https://download.youkuaiyun.com/download/hq091117/10937572
首先在接口里:
path:html模板路径,model是填的内容,out是输出流
String content = TemplateUtils.getTranslateTemplate(path, model);
new PdfGenerator().generate(content, out);
读取模板工具类
public class TemplateUtils {
public static String getTranslateTemplate(String path, Map<String, Object> model) throws Exception {
String content = null;Configuration config = FreemarkerConfiguration.getConfiguation();
config.setDefaultEncoding("UTF-8");
Template template = config.getTemplate(path);
content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
// StringWriter stringWriter = new StringWriter();
// BufferedWriter writer = new BufferedWriter(stringWriter);
// template.setEncoding("UTF-8");
// template.process(model, writer);
// content = stringWriter.toString();
// writer.flush();
// writer.close();
return content;
}
读取模板所在路径类
public class FreemarkerConfiguration {
private static Configuration config = null;
static {
config = new Configuration();
config.setClassForTemplateLoading(FreemarkerConfiguration.class, "/template");
}public static Configuration getConfiguation() {
return config;
}}
转PDF类
package com.zh.audit.confirmation.htmltopdf;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;import org.apache.commons.lang3.StringUtils;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.exceptions.CssResolverException;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.net.FileRetrieve;
import com.itextpdf.tool.xml.net.ReadingProcessor;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.AbstractImageProvider;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.itextpdf.tool.xml.pipeline.html.ImageProvider;
import com.itextpdf.tool.xml.pipeline.html.NoImageProviderException;public class PdfGenerator {
private static final String CHARSET_NAME = "UTF-8";
public void generate(String htmlStr, OutputStream out) throws IOException, DocumentException, CssResolverException {
Document document = new Document(PageSize.A4, 30, 30, 30, 30);
document.setMargins(30, 30, 30, 30);
PdfWriter writer = PdfWriter.getInstance(document, out);
PdfFileExportUtil pdfFileExportUtil = new PdfFileExportUtil();
writer.setPageEvent(pdfFileExportUtil.new HeadFootInfoPdfPageEvent());
document.open();// html内容解析
HtmlPipelineContext htmlContext = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider() {
@Override
public Font getFont(String fontName, String encoding, float size, final int style) {
Font font = null;
if (fontName == null || "宋体".equals(fontName) || "simsun".equals(fontName)) {
// 字体
String fontCn = getSIMSUNFont();
BaseFont bf;
try {
// 注意这里有一个,1
bf = BaseFont.createFont(fontCn + ",1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
font = new Font(bf, size, style);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}}
return font;
}
})) {
@Override
public HtmlPipelineContext clone() throws CloneNotSupportedException {
HtmlPipelineContext context = super.clone();
try {
ImageProvider imageProvider = this.getImageProvider();
context.setImageProvider(imageProvider);
} catch (NoImageProviderException e) {
}
return context;
}
};// 图片解析
htmlContext.setImageProvider(new AbstractImageProvider() {// String rootPath = servletContext.getRealPath("/");
@Override
public String getImageRootPath() {
return "";
}@Override
public Image retrieve(String src) {
if (StringUtils.isEmpty(src)) {
return null;
}
try {
// String imageFilePath = new File(rootPath,
// src).toURI().toString();
Image image = Image.getInstance(src);
image.setAbsolutePosition(400, 400);
if (image != null) {
store(src, image);
return image;
}
} catch (Throwable e) {
e.printStackTrace();
}
return super.retrieve(src);
}
});
htmlContext.setAcceptUnknown(true).autoBookmark(true).setTagFactory(Tags.getHtmlTagProcessorFactory());// css解析
CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
cssResolver.setFileRetrieve(new FileRetrieve() {
@Override
public void processFromStream(InputStream in, ReadingProcessor processor) {
try {
InputStreamReader reader = new InputStreamReader(in, CHARSET_NAME);
int i = -1;
while (-1 != (i = reader.read())) {
processor.process(i);
}
} catch (Throwable e) {}
}// 解析href
@Override
public void processFromHref(String href, ReadingProcessor processor) throws IOException {
URL url = new URL(href);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
InputStream is = conn.getInputStream();
InputStreamReader reader = new InputStreamReader(is, CHARSET_NAME);
try {
int i = -1;
while (-1 != (i = reader.read())) {
processor.process(i);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
});
// cssResolver.addCss(".div-0{font-size: 36px; text-align:
// center;}",true);
HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer));
Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser parser = new XMLParser(true, worker, Charset.forName(CHARSET_NAME));
InputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes(CHARSET_NAME));
try {
parser.parse(inputStream, Charset.forName(CHARSET_NAME));
} catch (Throwable e) {
e.printStackTrace();
}
document.close();
}/**
* 获取中文字体位置
*
* @return
*/
private String getSIMSUNFont() {String font = this.getClass().getResource("/").getPath() + "template/SIMSUN.TTC";
// String font = "D:/tmp/SIMSUN.TTC";
// System.out.println(font);
if (!new File(font).exists()) {
throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!" + font);
}return font;
}
}
操作PDF的工具类
package com.zh.audit.confirmation.htmltopdf;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;public class PdfFileExportUtil {
private static Font pdf8Font = null;
private static Font pdf20Font = null;/**
* 获取中文字符集且是8号字体,常用作表格内容的字体格式
*
* @return
* @throws DocumentException
* @throws IOException
*/
public static Font getChinese8Font() throws DocumentException, IOException {
if (pdf8Font == null) {
// 设置中文字体和字体样式
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
pdf8Font = new Font(bfChinese, 10, Font.NORMAL);
}
return pdf8Font;
}/**
* 获取中文字符集且是8号字体,常用作文字水印信息
*
* @return
* @throws DocumentException
* @throws IOException
*/
public static Font getChinese20Font() throws DocumentException, IOException {
if (pdf20Font == null) {
// 设置中文字体和字体样式
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
pdf20Font = new Font(bfChinese, 20, Font.BOLD);
}
return pdf20Font;
}/**
* 设置只读
*
* @param pdfWriter
* @return
* @throws DocumentException
*/
public static PdfWriter setReadOnlyPDFFile(PdfWriter pdfWriter) throws DocumentException {
pdfWriter.setEncryption(null, null, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
return pdfWriter;
}/**
* 图片水印
*
* @param waterMarkImage
* @param xPosition
* @param yPosition
* @return
*/
public static Image getWaterMarkImage(Image waterMarkImage, float xPosition, float yPosition) {
waterMarkImage.setAbsolutePosition(xPosition, yPosition);// 坐标
waterMarkImage.setRotation(-20);// 旋转弧度
waterMarkImage.setRotationDegrees(-45);// 旋转角度
waterMarkImage.scalePercent(100);// 依照比例缩放
return waterMarkImage;
}/**
* 文本水印
*
* @author wangjing
*
*/
class TextWaterMarkPdfPageEvent extends PdfPageEventHelper {
private String waterMarkText;public TextWaterMarkPdfPageEvent(String waterMarkText) {
this.waterMarkText = waterMarkText;
}public void onEndPage(PdfWriter writer, Document document) {
try {
float pageWidth = document.right() + document.left();// 获取pdf内容正文页面宽度
float pageHeight = document.top() + document.bottom();// 获取pdf内容正文页面高度
// 设置水印字体格式
Font waterMarkFont = PdfFileExportUtil.getChinese20Font();
PdfContentByte waterMarkPdfContent = writer.getDirectContentUnder();
Phrase phrase = new Phrase(waterMarkText, waterMarkFont);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f,
pageHeight * 0.2f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f,
pageHeight * 0.5f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.25f,
pageHeight * 0.8f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f,
pageHeight * 0.2f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f,
pageHeight * 0.5f, 45);
ColumnText.showTextAligned(waterMarkPdfContent, Element.ALIGN_CENTER, phrase, pageWidth * 0.65f,
pageHeight * 0.8f, 45);
} catch (Exception e) {
e.printStackTrace();
}
}/**
* 图片水印
*
* @author wangjing
*
*/
class PictureWaterMarkPdfPageEvent extends PdfPageEventHelper {
private String waterMarkFullFilePath;
private Image waterMarkImage;public PictureWaterMarkPdfPageEvent(String waterMarkFullFilePath) {
this.waterMarkFullFilePath = waterMarkFullFilePath;
}public void onEndPage(PdfWriter writer, Document document) {
try {
float pageWidth = document.right() + document.left();// 获取pdf内容正文页面宽度
float pageHeight = document.top() + document.bottom();// 获取pdf内容正文页面高度
PdfContentByte waterMarkPdfContent = writer.getDirectContentUnder();
// 仅设置一个图片实例对象,整个PDF文档只应用一个图片对象,极大减少因为增加图片水印导致PDF文档大小增加
if (waterMarkImage == null) {
waterMarkImage = Image.getInstance(waterMarkFullFilePath);
}
// 添加水印图片,文档正文内容采用横向三列,竖向两列模式增加图片水印
waterMarkPdfContent
.addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.2f, pageHeight * 0.1f));
waterMarkPdfContent
.addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.2f, pageHeight * 0.4f));
waterMarkPdfContent
.addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.2f, pageHeight * 0.7f));
waterMarkPdfContent
.addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.6f, pageHeight * 0.1f));
waterMarkPdfContent
.addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.6f, pageHeight * 0.4f));
waterMarkPdfContent
.addImage(getWaterMarkImage(waterMarkImage, pageWidth * 0.6f, pageHeight * 0.7f));
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.2f);// 设置透明度为0.2
waterMarkPdfContent.setGState(gs);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}/**
* 页脚(第几页)
*
* @author wangjing
*
*/
class HeadFootInfoPdfPageEvent extends PdfPageEventHelper {
public HeadFootInfoPdfPageEvent() {
}public void onEndPage(PdfWriter writer, Document document) {
try {
PdfContentByte headAndFootPdfContent = writer.getDirectContent();
headAndFootPdfContent.saveState();
headAndFootPdfContent.beginText();
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
headAndFootPdfContent.setFontAndSize(bfChinese, 15);
// 文档页头信息设置
// float x = document.top(-20);
// headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_RIGHT,
// "-", document.right(), x, 0);
// 文档页脚信息设置
float y = document.bottom(-20);
// 页脚信息左面
// headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_LEFT,
// "--", document.left(), y, 0);
// 页脚信息中间
headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_CENTER, "第" + writer.getPageNumber() + "页",
(document.right() + document.left()) / 2, y, 0);
// 页脚信息右面
// headAndFootPdfContent.showTextAligned(PdfContentByte.ALIGN_RIGHT,
// "--", document.right(), y, 0);
headAndFootPdfContent.endText();
headAndFootPdfContent.restoreState();
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}}
}