itextpdf 的基本使用
823人浏览 / 0人评论
参考
https://blog.csdn.net/lyf_ldh/article/details/99955292
引入依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
示例
PdfUtils.java
import com.google.common.collect.Lists;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import me.zhengjie.modules.document.domain.StandardDetail;
import me.zhengjie.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.util.IOUtils;
import java.io.*;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author 风仔
* @Date 2021/11/19
* @Version 1.0
* @Description:
**/
public class PdfUtils {
/**
* 将数据写到PDF文件
*
* @param target 目标路径
* @param data 原始数据
*/
public static void writeToPdf(String target, List<StandardDetail> data) {
try {
// A4纸大小
//Rectangle pageSize = new Rectangle(595.0F, 842.0F);
//Document document = new Document(pageSize, 30, 30, 50, 50);
//Document document = new Document(PageSize.A4);
Document document = new Document(PageSize.A4.rotate(), 15, 15, 25, 15);
target = target.replace(".pdf", "-1.pdf");
File file = new File(target);
// 使用PDFWriter进行写文件操作
PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
// 添加标题
Paragraph paragraph = new Paragraph("评分详情表", new Font(getBaseFont(), 15, Font.BOLD));
paragraph.setAlignment(Element.ALIGN_CENTER);
paragraph.setSpacingAfter(10f);
document.add(paragraph);
// 添加表格
PdfPTable table = addTable();
// 单元格
PdfPCell cell;
// 处理数据
Map<Long, List<StandardDetail>> map1 = data.stream().collect(Collectors.groupingBy(StandardDetail::getId1));
Long[] objects1 = map1.keySet().toArray(new Long[0]);
for (Long o1 : objects1) {
List<StandardDetail> list1 = map1.get(o1);
// 类别
cell = getVerticalCell(list1.get(0).getId1Name());
// 行合并
cell.setRowspan(list1.size());
table.addCell(cell);
Map<Long, List<StandardDetail>> map2 = list1.stream().collect(Collectors.groupingBy(StandardDetail::getId2));
for (Long o2 : sort(map2.keySet().toArray(new Long[0]))) {
List<StandardDetail> list2 = map2.get(o2);
if (CollectionUtils.isNotEmpty(list2)) {
// 项目
cell = getVerticalCell(list2.get(0).getId2Name());
cell.setRowspan(list2.size());
table.addCell(cell);
Map<Long, List<StandardDetail>> map3 = list2.stream().collect(Collectors.groupingBy(StandardDetail::getId2));
Long[] objects3 = map3.keySet().toArray(new Long[0]);
for (Long o3 : objects3) {
List<StandardDetail> list3 = map3.get(o3);
if (CollectionUtils.isNotEmpty(list3)) {
for (StandardDetail standardDetail : list3) {
// 内容
cell = getContentCell(standardDetail.getId3Name());
table.addCell(cell);
// 标准分值
cell = getCell(standardDetail.getScore().toString());
table.addCell(cell);
// 评分原则
cell = getRuleCell(standardDetail.getContent());
table.addCell(cell);
// 评审描述
cell = getContentCell(standardDetail.getReason());
table.addCell(cell);
// 实际得分
cell = getCell(String.valueOf(standardDetail.getScore() - standardDetail.getDeduction()));
table.addCell(cell);
}
}
}
}
}
}
document.add(table);
document.close();
addPageNum(target, target.replace("-1.pdf", "-2.pdf"));
file.delete();
} catch (DocumentException | FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 生成表格对象
*
* @return PdfPTable
*/
private static PdfPTable addTable() {
PdfPTable table = new PdfPTable(7);
// 单元格
PdfPCell cell;
cell = getCell("类别");
table.addCell(cell);
cell = getCell("项目");
table.addCell(cell);
cell = getCell("内容");
table.addCell(cell);
cell = getCell("标准分值");
table.addCell(cell);
cell = getCell("评分原则");
table.addCell(cell);
cell = getCell("评审描述");
table.addCell(cell);
cell = getCell("实际得分");
table.addCell(cell);
// 设置列宽
float[] colWidths = {5f, 5f, 30f, 5f, 30f, 30f, 5f};
try {
table.setTotalWidth(colWidths);
} catch (DocumentException e) {
e.printStackTrace();
}
return table;
}
/**
* 添加页码
*
* @param source 原文件路径
* @param target 目标文件路径
*/
private static void addPageNum(String source, String target) {
try (FileOutputStream fos = new FileOutputStream(target)) {
// 新建文档,默认A4大小
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, fos);
// 设置页面监听事件,必须在open方法前
writer.setPageEvent(new PageNumPdfPageEvent());
document.open();
// PDF内容体
PdfContentByte pdfContent = writer.getDirectContent();
// 读取 源PDF文件,进行一页一页复制,才能触发 添加页码的 页面监听事件
PdfReader reader = new PdfReader(source);
// 获取 源文件总页数
int num = reader.getNumberOfPages();
// 页面数是从1开始的
for (int i = 1; i <= num; i++) {
document.newPage();
// 设置空页码进行展示
writer.setPageEmpty(false);
PdfImportedPage page = writer.getImportedPage(reader, i);
// 复制好的页面,添加到内容去,触发事件监听
pdfContent.addTemplate(page, 0, 0);
}
document.close();
reader.close();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
imageWatermark(target, target.replace("-2.pdf", ".pdf"));
}
/**
* 添加图片水印
*
* @param inputPath 原文件路径
* @param outputPath 目标文件路径
*/
public static void imageWatermark(String inputPath, String outputPath) {
PdfReader reader = null;
PdfStamper stamp = null;
try {
reader = new PdfReader(inputPath);
stamp = new PdfStamper(reader, new FileOutputStream(outputPath));
PdfGState gs1 = new PdfGState();
gs1.setFillOpacity(0.1f);
String s = Objects.requireNonNull(PdfUtils.class.getClassLoader().getResource("")).toString();
s = s.replace("file:/", "");
s = s.replace("eladmin-common", "eladmin-system");
s = s.replace("classes/", "classes/image/logo.png");
Image image = Image.getInstance(IOUtils.toByteArray(new FileInputStream(s)));
int n = reader.getNumberOfPages();
for (int i = 1; i <= n; i++) {
PdfContentByte pdfContentByte = stamp.getOverContent(i);
pdfContentByte.setGState(gs1);
image.setAbsolutePosition(180, 300);
// 等比缩放 100为原本大小
image.scalePercent(200);
// 旋转角度 正数向左,负数向右
//image.setRotationDegrees(45);
pdfContentByte.addImage(image);
}
} catch (DocumentException | IOException e) {
e.printStackTrace();
} finally {
try {
stamp.close();
reader.close();
new File(inputPath).delete();
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
}
/**
* 生成常规单元格
*
* @param value 单元格内容
* @return PdfPCell
*/
private static PdfPCell getCell(String value) {
PdfPCell cell = new PdfPCell(new Phrase(value, new Font(getBaseFont(), 12)));
cell.setUseAscender(true);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setBorderColor(BaseColor.GRAY);
return cell;
}
/**
* 生成垂直单元格
*
* @param value 单元格内容
* @return PdfPCell
*/
private static PdfPCell getVerticalCell(String value) {
value = value.replace(" ", " ");
// 正常字体
Font font = new Font(getBaseFont(), 12);
String[] split = value.split(" ");
PdfPCell cell = new PdfPCell();
Paragraph number = new Paragraph(split[0], font);
if (split[0].length() > 1) {
number.setFirstLineIndent(6);
} else {
number.setFirstLineIndent(10);
}
cell.addElement(number);
List<String> list = splitChineseWord(split[1], 2);
for (String s : list) {
Paragraph chinese = new Paragraph(s, font);
chinese.setFirstLineIndent(8);
cell.addElement(chinese);
}
cell.setUseAscender(true);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setBorderColor(BaseColor.GRAY);
return cell;
}
/**
* 排序
*
* @param objects Long[]
* @return Long[]
*/
private static Long[] sort(Long[] objects) {
Long temp;
for (int i = 0; i < objects.length; i++) {
//j是数组的最后一个角标
for (int j = objects.length - 1; j > i; j--) {
if (objects[j] < objects[j - 1]) {
//从后往前进行比较,小数往前,一轮之后最小数就在最前面了
temp = objects[j - 1];
objects[j - 1] = objects[j];
objects[j] = temp;
}
}
}
return objects;
}
/**
* 将字符串拆分成单个汉字
*
* @param str 源字符串
* @param mod 拆分级别 eg: mod = 1 或 mod = 2 拆分成1个单词, mod = 4 差分成两个单词
* @return List<String>
*/
private static List<String> splitChineseWord(String str, int mod) {
List<String> result = Lists.newArrayList();
List<String> list = Lists.newArrayList();
int chLetter = 0;
byte[] stringToByte;
int k = 0;
byte[] temp;
try {
temp = new byte[mod];
stringToByte = str.getBytes("gbk");
for (int i = 0; i < stringToByte.length; i++) {
//根据GBK编码,汉字都是小于0,并分为2个byte存放
if (stringToByte[i] < 0) {
if (k < mod - 1) {
temp[k] = stringToByte[i];
temp[++k] = stringToByte[++i];
k++;
if (k == mod) {
list.add(new String(temp, "gbk"));
k = 0;
}
} else {
byte[] emitLetter = new byte[2];
emitLetter[0] = stringToByte[i];
emitLetter[1] = stringToByte[i + 1];
i = i + 1;
chLetter = chLetter + 2;
result.add(new String(emitLetter, "gbk"));
}
} else {
temp[k] = stringToByte[i];
k++;
if (k == mod) {
list.add(new String(temp, "gbk"));
k = 0;
}
}
if (i == stringToByte.length - 1) {
byte[] lastData = new byte[k];
System.arraycopy(temp, 0, lastData, 0, k);
list.add(new String(lastData, "gbk"));
}
}
} catch (UnsupportedEncodingException ex) {
System.out.println("no gbk");
}
if (CollectionUtils.isNotEmpty(list) && StringUtils.isNotBlank(list.get(0))) {
return list;
} else {
return result;
}
}
/**
* 生成内容单元格
*
* @param value 单元格内容
* @return PdfPCell
*/
private static PdfPCell getContentCell(String value) {
PdfPCell cell = new PdfPCell(new Phrase(value, new Font(getBaseFont(), 12)));
// 设置可以居中
cell.setUseAscender(true);
// 设置垂直对齐
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
// 设置水平对齐
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
// 设置缩进
cell.setIndent(24);
// 设置行距 param1 * param2
cell.setLeading(15, 0);
// 设置内边距
cell.setPadding(10);
// 设置边框颜色
cell.setBorderColor(BaseColor.GRAY);
return cell;
}
/**
* 生成评审原则单元格
*
* @param value 单元格内容
* @return PdfPCell
*/
private static PdfPCell getRuleCell(String value) {
// 正常字体
Font font = new Font(getBaseFont(), 12);
PdfPCell cell = new PdfPCell();
String[] paragraph = new String[0];
if (StringUtils.isNotBlank(value)) {
paragraph = value.split(" ");
}
Paragraph p;
for (String s : paragraph) {
p = new Paragraph(s, font);
// 首行缩进
p.setFirstLineIndent(24);
cell.addElement(p);
}
// 设置可以居中
cell.setUseAscender(true);
// 设置垂直对齐
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
// 设置水平对齐
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
// 设置行距 param1 * param2
cell.setLeading(15, 0);
// 设置内边距
cell.setPadding(10);
// 设置边框颜色
cell.setBorderColor(BaseColor.GRAY);
return cell;
}
/**
* 生成基础字体
*
* @return BaseFont
*/
private static BaseFont getBaseFont() {
String s = Objects.requireNonNull(PdfUtils.class.getClassLoader().getResource("")).toString();
s = s.replace("eladmin-common", "eladmin-system");
s = s.replace("classes/", "classes/font/仿宋_GB2312.ttf");
BaseFont baseFont = null;
try {
// 中文字体(现在高版本的不支持中文包)
//baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
baseFont = BaseFont.createFont(s, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
} catch (com.itextpdf.text.DocumentException | IOException e) {
e.printStackTrace();
}
return baseFont;
}
}
PageNumPdfPageEvent.java
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.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import org.springframework.stereotype.Component;
/**
* @author 风仔
*/
@Component
public class PageNumPdfPageEvent extends PdfPageEventHelper {
@Override
public void onEndPage(PdfWriter writer, Document document) {
try {
// PDF文档内容
PdfContentByte pdfContent = writer.getDirectContent();
pdfContent.saveState();
pdfContent.beginText();
int footerFontSize = 11;
// 解决页码中文无法显示 或者 显示为乱码的问题
// 但是必须引入jar包 itext-asian-5.2.0.jar
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
Font fontDetail = new Font(baseFont, footerFontSize, Font.NORMAL);
pdfContent.setFontAndSize(baseFont, footerFontSize);
// 页脚的页码 展示
String footerNum = String.format("%d", writer.getPageNumber());
Phrase phrase = new Phrase(footerNum, fontDetail);
// 页码的 横轴 坐标 居中
float x = (document.left() + document.right()) / 2;
// 页码的 纵轴 坐标
float y = document.bottom(-10);
// 添加文本内容,进行展示页码
ColumnText.showTextAligned(pdfContent, Element.ALIGN_CENTER, phrase, x, y, 0);
pdfContent.endText();
pdfContent.restoreState();
} catch (Exception e) {
e.printStackTrace();
}
}
}
全部评论