itext7生成PDF
程序员文章站
2024-03-19 12:57:04
...
1、配置
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.1.11</version>
<type>pom</type>
</dependency>
2.PDFUtils
封装的PDF工具类,导包直接选中itext相关的就好,注意IOException不要导itext的(第一次无脑导的后果…)
public class PDFUtils {
public static PdfFont getDefaultFont() {
try {
// return PdfFontFactory.createFont("C://windows//fonts//simsun.ttc,1", PdfEncodings.IDENTITY_H, false);// 引用系统字体
return PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", false);// 使用itext字体
} catch (IOException e) {
// 记录日志
e.printStackTrace();
}
return null;
}
public static PdfFont getImportFont(String fontName) {
// 获取resource下文件夹路径
String path = "/template/";
String fontPath = path + fontName;
try {
// 处理中文乱码(支持Linux系统)
FontProgram fontProgram = FontProgramFactory.createFont(fontPath, false);
PdfFont font = PdfFontFactory.createFont(fontProgram, PdfEncodings.IDENTITY_H, false);
return font;
} catch (IOException e) {
// 记录日志
e.printStackTrace();
}
return null;
}
public static final void replaceTextFieldPdf(String templatePdfPath, String destPdfPath,
Map<String, String> params) {
PdfDocument pdf = null;
try {
// 判断文件是否存在
File file = new File(destPdfPath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
// 有参数才替换
if (params != null && !params.isEmpty()) {
pdf = new PdfDocument(new PdfReader(templatePdfPath), new PdfWriter(destPdfPath));
PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
Map<String, PdfFormField> fields = form.getFormFields(); // 获取所有的表单域
for (String param : params.keySet()) {
PdfFormField formField = fields.get(param); // 获取某个表单域
if (formField != null) {
formField.setFont(getImportFont("SourceHanSansCN-Regular.ttf")).setValue(params.get(param)); // 替换值
// formField.setFont(getDefaultFont()).setValue(params.get(param)); // 替换值
}
}
form.flattenFields();// 锁定表单,不让修改
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (pdf != null) {
pdf.close();
}
}
}
public static final void replaceImageFieldPdf(String templatePdfPath, String destPdfPath,
Map<String, String> params) throws FileNotFoundException, IOException {
PdfDocument pdf = new PdfDocument(new PdfReader(templatePdfPath), new PdfWriter(destPdfPath));
if (params != null && !params.isEmpty()) {// 有参数才替换
PdfAcroForm form = PdfAcroForm.getAcroForm(pdf, true);
Map<String, PdfFormField> fields = form.getFormFields(); // 获取所有的表单域
for (String param : params.keySet()) {
PdfFormField formField = fields.get(param);
if (formField != null) {
replaceFieldImage(params, pdf, param, formField); // 替换图片
}
}
form.flattenFields();// 锁定表单,不让修改
}
pdf.close();
}
private static final void replaceFieldImage(Map<String, String> params, PdfDocument pdf, String param,
PdfFormField formField) throws MalformedURLException {
String value = params.get(param);
String[] values = value.split("\\|");
Rectangle rectangle = formField.getWidgets().get(0).getRectangle().toRectangle(); // 获取表单域的xy坐标
PdfCanvas canvas = new PdfCanvas(pdf.getPage(Integer.parseInt(values[0])));
ImageData image = ImageDataFactory.create(values[1]);
float imageWidth = image.getWidth();
float imageHeight = image.getHeight();
float rectangleWidth = rectangle.getWidth();
float rectangleHeight = rectangle.getHeight();
float tempWidth = 0;
float tempHeight = 0;
int result = 1; // 压缩宽度
if (imageWidth > rectangleWidth) {
tempHeight = imageHeight * rectangleWidth / imageWidth;
if (tempHeight > rectangleHeight) {
tempHeight = rectangleHeight;
result = 2; // 压缩高度
} else {
tempWidth = rectangleWidth;
tempHeight = imageHeight * rectangleWidth / imageWidth;
}
} else {
if (imageHeight > rectangleHeight) {
tempHeight = rectangleHeight;
result = 2;
} else {
result = 3;
}
}
float y = 0;
if (result == 1) { // 压缩宽度
y = rectangleHeight - tempHeight;
} else if (result == 3) { // 不压缩
y = rectangleHeight - imageHeight;
}
// y/=2; // 如果想要图片在表单域的上下对齐,这个值除以2就行。同理可以计算x的偏移
if (result == 1) {
canvas.addImage(image, rectangle.getX(), rectangle.getY() + y, tempWidth, false);
} else if (result == 2) {
canvas.addImage(image, rectangle.getX(), rectangle.getY(), tempHeight, false, false);
} else if (result == 3) {
canvas.addImage(image, rectangle.getX(), rectangle.getY() + y, false);
}
}
@SuppressWarnings("resource")
public static final void addWatermark(String srcPdfPath, String destPdfPath, String watermarkText)
throws FileNotFoundException, IOException {
// 判断文件是否存在
File f1 = new File(srcPdfPath);
if (!f1.exists()) {
return;
}
// 判断文件是否存在
File f2 = new File(destPdfPath);
if (!f2.getParentFile().exists()) {
f2.getParentFile().mkdirs();
}
PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcPdfPath), new PdfWriter(destPdfPath));
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, new IEventHandler() {
@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = docEvent.getDocument();
PdfPage page = docEvent.getPage();
PdfFont font = null;
font = getImportFont("STSong.ttf"); // 要显示中文水印的话,需要设置中文字体
PdfCanvas canvas = new PdfCanvas(page);
PdfExtGState gs1 = new PdfExtGState();
gs1.setFillOpacity(0.7f); // 水印透明度
canvas.setExtGState(gs1);
new Canvas(canvas, pdfDoc, page.getPageSize()).setFontColor(ColorConstants.LIGHT_GRAY) // 颜色
.setFontSize(60) // 字体大小
.setFont(font) // 字体的格式 即导入的字体包
// 水印的内容(中英文都支持) 坐标(例如:298f, 421f) 当前页数 最后的值为倾斜度(170)
.showTextAligned(new Paragraph(watermarkText), 298, 421, pdfDoc.getPageNumber(page),
TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45);
}
});
pdfDoc.close();
}
public static boolean pdfMerger(List<String> paths, String outputPath) {
if (paths == null || paths.isEmpty() || StringUtils.isBlank(outputPath)) {
return false;
}
// 首页与其他页创建方式不同,所以需要创建两个
PdfDocument firstSourcePdf = null;
PdfDocument secondSourcePdf = null;
// 合并需要的工具类
PdfMerger merger = null;
try {
for (int i = 0; i < paths.size(); i++) {
if (i == 0) {
PdfWriter pdfWriter = new PdfWriter(outputPath);
// 启用完全压缩
// pdfWriter.isFullCompression();
firstSourcePdf = new PdfDocument(new PdfReader(paths.get(i)), pdfWriter);
merger = new PdfMerger(firstSourcePdf);
continue;
}
secondSourcePdf = new PdfDocument(new PdfReader(paths.get(i)));
merger.merge(secondSourcePdf, 1, secondSourcePdf.getNumberOfPages());
secondSourcePdf.close();
}
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
if (firstSourcePdf != null) {
firstSourcePdf.close();
}
if (secondSourcePdf != null) {
secondSourcePdf.close();
}
if (merger != null) {
merger.close();
}
}
return false;
}
public static String downPdf(HttpServletResponse response, String reviewName, String outputFilePath) {
File file = new File(outputFilePath);
if (!file.exists()) {
return "下载文件不存在";
}
// 设置格式
try {
response.reset();
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(reviewName, "UTF-8"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// 文件写出
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
byte[] buff = new byte[1024];
OutputStream os = response.getOutputStream();
int i = 0;
while ((i = bis.read(buff)) != -1) {
os.write(buff, 0, i);
os.flush();
}
} catch (Exception e) {
return "下载失败";
} finally {
// 删除服务器文件
forceDelete(file);
}
return "下载成功";
}
public static boolean forceDelete(File f) {
boolean result = false;
int tryCount = 0;
while (!result && tryCount++ < 10) {
// System.gc();
result = f.delete();
}
return result;
}
public static int forceBatchDelete(List<String> paths) {
if (paths == null || paths.isEmpty()) {
return 0;
}
int result = 0;
for (int i = 0; i < paths.size(); i++) {
boolean delete = forceDelete(new File(paths.get(i)));
if (delete) {
result++;
}
}
return result;
}
}
3、页码
/**
* @author QiaoFengTao
* @Title:
* @Description: 生成页码辅助类
* @date 2021/7/5 15:54
*/
public class TextFooterEventHandler implements IEventHandler {
private Document document;
private PdfFont font;
public TextFooterEventHandler(Document document, PdfFont font){
this.document = document;
this.font = font;
}
@Override
public void handleEvent(Event event) {
PdfDocumentEvent pdfEvent = (PdfDocumentEvent) event;
PdfPage page = pdfEvent.getPage();
PdfDocument pdfDoc = pdfEvent.getDocument();
//获取当前页码
int pageNumber = pdfDoc.getPageNumber(page);
PdfCanvas pdfCanvas = new PdfCanvas(page);
PageSize pageSize = pdfDoc.getDefaultPageSize();
pdfCanvas.beginText()
.setFontAndSize(this.font, 12)
.moveText(pageSize.getWidth() / 2 - 30, 20)
.showText("- 第 " + pageNumber + " 页 -")
.endText()
.release();
}
}
4、页眉页脚
/**
* 页眉页脚
* @author QiaoFengTao
* @date 2021/7/15 18:41
*/
public class HeaderFooterHandler implements IEventHandler {
private PdfFont font;
public HeaderFooterHandler(PdfFont font) {
this.font = font;
}
@Override
public void handleEvent( Event event) {
try {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = docEvent.getDocument();
Document doc = new Document(pdfDoc);
PdfPage page = docEvent.getPage();
Rectangle pageSize = page.getPageSize();
float pdfWidth = pageSize.getWidth();
float pdfHeight = pageSize.getHeight();
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
float tableWidth = pdfWidth - doc.getRightMargin() - doc.getLeftMargin();
// 页眉
float x0 = doc.getRightMargin(), y0 = pdfHeight - doc.getTopMargin() - 20;
pdfCanvas.moveTo(x0, y0);
Paragraph pageNameParagraph = new Paragraph();
pageNameParagraph.setVerticalAlignment(VerticalAlignment.BOTTOM);
pageNameParagraph.add(getLogoImage());
pageNameParagraph.setTextAlignment(TextAlignment.RIGHT);
pageNameParagraph.setFixedPosition(x0, y0, tableWidth);
doc.add(pageNameParagraph);
} catch (final Exception e) {
e.printStackTrace();
}
}
/*
* 页眉logo
**/
private Image getLogoImage() {
ClassPathResource resources = new ClassPathResource("\\static\\image\\header_logo.png");
Image headerImg = null;
try {
headerImg = new Image(ImageDataFactory.create(resources.getURI().toString()));
} catch (IOException e) {
e.printStackTrace();
}
headerImg.scaleToFit(120, 150);
return headerImg;
}
}
5、添加图片到每页
/**
* @author QiaoFengTao
* @date 2021/7/19 18:02
*/
public class BackgroundEventHandler implements IEventHandler {
public BackgroundEventHandler() {
}
@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = docEvent.getDocument();
PdfPage page = docEvent.getPage();
Rectangle pageSize = page.getPageSize();
float pdfWidth = pageSize.getWidth();
ClassPathResource resources = new ClassPathResource("\\static\\image\\pdf_bk.jpg");
ImageData images = null;
try {
images = ImageDataFactory.create(resources.getURI().toString());
images.setWidth(pdfWidth);
} catch (IOException e) {
e.printStackTrace();
}
PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
canvas.addImage(images,0,0,true);
}
}