PDF生成工具类
package com.zhongan.life.printer.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.zhongan.life.printer.common.Common500Exception;
import com.zhongan.life.printer.common.CommonException;
import com.zhongan.life.printer.common.enums.DtcErrorEnum;
import com.zhongan.life.printer.model.dto.printer.request.PdfPrintParam;
import com.zhongan.life.printer.service.configs.FontProviderConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
@Slf4j
public class PDFKit {
//PDF页眉、页脚定制工具
private HeaderFooterBuilder headerFooterBuilder;
/**
* @param fileName 输出PDF文件名
* @param data 模板所需要的数据
* @description 导出pdf到文件
*/
public String exportToFile(String fileName, Object data, Path templatePath) throws IOException {
// 获取临时路径
Path pdfFilePath = Files.createTempFile(fileName, ".pdf");
FreeMarkerUtil freeMarkerUtil = new FreeMarkerUtil();
// freeMarker 转换
String htmlData = freeMarkerUtil.getContent(fileName, data, templatePath);
FileOutputStream outputStream = null;
try {
//设置输出路径
outputStream = new FileOutputStream(pdfFilePath.toFile());
//设置文档大小
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
//设置页眉页脚
PDFBuilder builder = new PDFBuilder(headerFooterBuilder, data);
builder.setPresentFontSize(10);
writer.setPageEvent(builder);
//输出为PDF文件
convertToPDF(writer, document, htmlData);
return pdfFilePath.toString();
} catch (Exception ex) {
ex.printStackTrace();
log.error("exportToFile:{}", ex.getMessage());
throw new Common500Exception(DtcErrorEnum.PDF_GENERATION_ERROR, ExceptionUtils.getFullStackTrace(ex));
} finally {
// 删除模板的临时文件
IOUtils.closeQuietly(outputStream);
}
}
/**
* @description PDF文件生成
*/
private void convertToPDF(PdfWriter writer, Document document, String htmlString) {
//获取字体路径
// String fontPath = getFontPath();
document.open();
try {
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new ByteArrayInputStream(htmlString.getBytes("UTF-8")),
null,
Charset.forName("UTF-8"), new FontProviderConfig());
} catch (IOException e) {
throw new CommonException(DtcErrorEnum.IOEXCEPTION);
} finally {
document.close();
}
}
/**
* @description 创建默认保存路径
*/
private String getDefaultSavePath(String fileName) {
String classpath = PDFKit.class.getClassLoader().getResource("").getPath();
String saveFilePath = classpath + "pdf/" + fileName;
File f = new File(saveFilePath);
if (!f.getParentFile().exists()) {
f.mkdirs();
}
return saveFilePath;
}
/**
* @description 获取字体设置路径
*/
public static String getFontPath() {
String classpath = PDFKit.class.getClassLoader().getResource("").getPath();
String fontpath = classpath + "fonts";
return fontpath;
}
public HeaderFooterBuilder getHeaderFooterBuilder() {
return headerFooterBuilder;
}
public void setHeaderFooterBuilder(HeaderFooterBuilder headerFooterBuilder) {
this.headerFooterBuilder = headerFooterBuilder;
}
}
package com.zhongan.life.printer.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
/**
* PDF页眉页脚
*/
public interface HeaderFooterBuilder {
/**
* @description 写页眉
*/
void writeHeader(PdfWriter writer, Document document, Object data, Font font, PdfTemplate template);
/**
* @description 写页脚
*/
void writeFooter(PdfWriter writer, Document document, Object data, Font font, PdfTemplate template);
/**
* @description 关闭文档前,获取替换页眉页脚处设置模板的文本
*/
String getReplaceOfTemplate(PdfWriter writer, Document document, Object data);
}
package com.zhongan.life.printer.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
/**
* 页眉页脚定制工具
*/
public class PDFHeaderFooter implements HeaderFooterBuilder {
/**
* @param writer PDF编写类
* @param document PDF文档对象
* @param data 业务数据
* @param font 字体设置
* @param template PDF模板
* @description PDF页脚设置类
*/
@Override
public void writeFooter(PdfWriter writer,
Document document,
Object data,
Font font,
PdfTemplate template) {
if (data == null) {
return;
}
int pageS = writer.getPageNumber();
// int currentPage = pageS - 1;
// if (currentPage <= 0) {
// return;
// }
Phrase footer1 = new Phrase("页脚一", font);
Phrase footer2 = new Phrase("页脚二" + " " + pageS + "/", font);
PdfContentByte cb = writer.getDirectContent();
ColumnText.showTextAligned(
cb,
Element.ALIGN_LEFT,
footer1,
(document.left() + 10),
document.bottom() - 20,
0);
ColumnText.showTextAligned(
cb,
Element.ALIGN_RIGHT,
footer2,
(document.right() - 30),
document.bottom() - 20, 0);
//设置模板位置
cb.addTemplate(template, document.right() - 30, document.bottom() - 20);
}
/**
* @param writer PDF编写类
* @param document PDF文档对象
* @param data 业务数据
* @param font 字体设置
* @param template PDF模板
* @description PDF页头设置类
*/
@Override
public void writeHeader(PdfWriter writer,
Document document,
Object data,
Font font,
PdfTemplate template) {
ColumnText.showTextAligned(
writer.getDirectContent(),
Element.ALIGN_LEFT,
new Phrase("众安国际", font),
document.left(),
document.top() + 20, 0);
}
/**
* @param writer PDF编写类
* @param document PDF文档对象
* @param data 业务数据
* @description 页头、页眉设置的模板替换类
*/
@Override
public String getReplaceOfTemplate(PdfWriter writer, Document document, Object data) {
int total = writer.getPageNumber() - 2;
return total + "";
}
}
package com.zhongan.life.printer.utils;
import com.google.common.collect.Maps;
import com.zhongan.life.printer.common.CommonException;
import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import java.io.*;
import java.nio.file.Path;
import java.util.Map;
/**
*
* FREEMARKER 模板工具类
*/
@Slf4j
@Component
public class FreeMarkerUtil {
private static final String WINDOWS_SPLIT = "\\";
private static final String UTF_8 = "UTF-8";
private static Map<String, FileTemplateLoader> fileTemplateLoaderCache = Maps.newConcurrentMap();
private static Map<String, Configuration> configurationCache = Maps.newConcurrentMap();
public static Configuration getConfiguration(String templateFilePath) {
if (null != configurationCache.get(templateFilePath)) {
return configurationCache.get(templateFilePath);
}
Configuration config = new Configuration(Configuration.VERSION_2_3_25);
config.setDefaultEncoding(UTF_8);
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
config.setLogTemplateExceptions(false);
FileTemplateLoader fileTemplateLoader = null;
if (null != fileTemplateLoaderCache.get(templateFilePath)) {
fileTemplateLoader = fileTemplateLoaderCache.get(templateFilePath);
}
try {
fileTemplateLoader = new FileTemplateLoader(new File(templateFilePath));
fileTemplateLoaderCache.put(templateFilePath, fileTemplateLoader);
} catch (IOException e) {
e.printStackTrace();
}
config.setTemplateLoader(fileTemplateLoader);
configurationCache.put(templateFilePath, config);
return config;
}
/**
* @description 获取模板
*/
public String getContent(String fileName, Object data, Path templatePath) {
try (StringWriter writer = new StringWriter();) {
String templateFileName = getTemplateName(templatePath.toString());
String templateFilePath = getTemplatePath(templatePath.toString());
Template template = getConfiguration(templateFilePath).getTemplate(templateFileName);
template.process(data, writer);
writer.flush();
return writer.toString();
} catch (Exception ex) {
ex.printStackTrace();
throw new CommonException("", "FreeMarkerUtil process fail", ex.getMessage());
}
}
private String getTemplatePath(String templatePath) {
if (StringUtils.isEmpty(templatePath)) {
return "";
}
if (templatePath.contains(WINDOWS_SPLIT)) {
return templatePath.substring(0, templatePath.lastIndexOf(WINDOWS_SPLIT));
}
return templatePath.substring(0, templatePath.lastIndexOf("/"));
}
private String getTemplateName(String templatePath) {
if (StringUtils.isEmpty(templatePath)) {
return "";
}
if (templatePath.contains(WINDOWS_SPLIT)) {
return templatePath.substring(templatePath.lastIndexOf(WINDOWS_SPLIT) + 1);
}
return templatePath.substring(templatePath.lastIndexOf("/") + 1);
}
}
调用
// PDFHeaderFooter headerFooter = new
// PDFHeaderFooter();
// PDFKit kit = new PDFKit();
// kit.setHeaderFooterBuilder(headerFooter);
// fileName 导出文件名 data模板替换值 templatePath 模板路径
// kit.exportToFile(fileName, data,templatePath);