更新时间:2021-11-29
@[PDF]工具类涉及:1.添加水印 2.设置签名域 3.获取文件签名域信息
这里的方法基于com.itextpdf.text包
maven坐标:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
1.添加水印
/**
*
* @param filePath 需要添加水印的文件
* @param waterMark 水印内容
* @param outPath 输出文件路径
* @throws Exception
*/
public static void waterMarkAdd(String filePath,String waterMark,String outPath) throws Exception{
byte[] bytes = getByteString(filePath);
PdfReader reader = new PdfReader(bytes);
PdfStamper stamper = new PdfStamper(reader,new FileOutputStream(outPath));
BaseFont baseFont = BaseFont.createFont();
Rectangle pageRect = null;
PdfGState pdfGState = new PdfGState();
pdfGState.setFillOpacity(0.3f);
pdfGState.setStrokeOpacity(0.4f);
int total = reader.getNumberOfPages()+1;
JLabel label = new JLabel();
FontMetrics fontMetrics;
int textHeight = 0;
int textWidth = 0;
label.setText(waterMark);
fontMetrics = label.getFontMetrics(label.getFont());
textHeight = fontMetrics.getHeight();
textWidth = fontMetrics.stringWidth(label.getText());
PdfContentByte contentByte;
int numJ = 0 ;
int numK = 0 ;
for(int i=1; i<total;i++){
pageRect = reader.getPageSizeWithRotation(i);
contentByte = stamper.getOverContent(i);
contentByte.saveState();
contentByte.setGState(pdfGState);
contentByte.beginText();
contentByte.setFontAndSize(baseFont,24);
contentByte.setColorFill(BaseColor.BLACK);
// 你可以随心所欲的改你自己想要的角度
for (int height = textHeight; height < pageRect
.getHeight(); height = height + textHeight * 5) {
numJ ++ ;
for (int width = textWidth; width < pageRect
.getWidth() + textWidth; width = width + textWidth * 3) {
numK ++ ;
// 设置水印文字成角度倾斜
contentByte.showTextAligned(Element.ALIGN_LEFT,
waterMark, width - textWidth, height - textWidth,
35);
}
}
// contentByte.showTextAligned(Element.ALIGN_LEFT,
// waterMark, reader.getPageSize(i).getWidth()/2, reader.getPageSize(i).getHeight()/2,
// 45);
// 添加水印文字
contentByte.endText();
}
stamper.close();
reader.close();
}
/**
* 文件转byte流
* @param path 文件路径
* @return 返回byte[]
* @throws IOException
*/
private static byte[] getByteString(String path) throws IOException {
File file = new File(path);
byte[] buf = new byte[1024];
int len = 0;
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while((len = fis.read(buf))!=-1){
bos.write(buf,0,len);
}
bos.flush();
fis.close();
bos.close();
return bos.toByteArray();
}
2.设置签名域
public static byte[] setSignArea(byte[] tail,Map position, List posConfigSet) throws Exception {
int xIndex = 0;
int yIndex = 0;
int yMax = 780;
int yMin = 72;
PdfReader reader = new PdfReader(tail);
ByteArrayOutputStream baoPdfStream = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, baoPdfStream);
// 创建数组签名域
int width = 50, height = 50;
int pageNo = position.getInt("PAGE_NUM");
float x_pos = Float.parseFloat(position.getString("X_POS"))-xIndex;
float y_pos = Float.parseFloat(position.getString("Y_POS"))-yIndex;
y_pos = y_pos > yMax ? yMax : y_pos;
y_pos = y_pos < yMin ? yMin : y_pos;
Rectangle areaSignatureRect =
new Rectangle(x_pos,y_pos,x_pos + width,y_pos + height);
PdfFormField pdfFormField = PdfFormField.createSignature(stamper.getWriter());
pdfFormField.setWidget(areaSignatureRect, PdfAnnotation.HIGHLIGHT_NONE);
pdfFormField.setFieldName("signatureOne"); // 签名域标识
pdfFormField.setPage(pageNo);
stamper.addAnnotation(pdfFormField, pageNo);
//必须关闭,否则创建的PDF为0KB
stamper.close();
return baoPdfStream.toByteArray();
}
3.查看签名域信息
需要 com.spire.pdf 包
/**
*
* @param filePath 文件路径
* @return list 返回签名域信息集
*/
public List<Map<String,String>> getSignature(String filePath) {
List<Map<String,String>> list = new ArrayList<>();
Map<String,String> result = new HashMap<>();
//创建PdfDocument实例
PdfDocument pdf = new PdfDocument();
//加载含有签名的PDF文件
pdf.loadFromFile(filePath);
//获取域集合
PdfFormWidget pdfFormWidget = (PdfFormWidget) pdf.getForm();
PdfFormFieldWidgetCollection pdfFormFieldWidgetCollection = pdfFormWidget.getFieldsWidget();
//遍历域
for (int i = 0; i < pdfFormFieldWidgetCollection.getCount(); i++) {
//判定是否为签名域
if (pdfFormFieldWidgetCollection.get(i) instanceof PdfSignatureFieldWidget) {
//获取签名域
PdfSignatureFieldWidget signatureFieldWidget = (PdfSignatureFieldWidget) pdfFormFieldWidgetCollection
.get(i);
//获取签名
PdfSignature signature = signatureFieldWidget.getSignature();
String location = signature.getLocationInfo();
String reason = signature.getReason();
String data = signature.getDate().toString();
String name = signature.getSignatureName();
result.put("location",location);
result.put("reason",reason);
result.put("data",data);
result.put("name",name);
list.add(result);
System.out.println(
"location:" + location + ",reason:" + reason + ",data:" + data + ",name:" + name);
}
}
return list;
}
4 获取关键字位置坐标
//因匿名内部类原因定义为成员变量
private int i = 0;
/**
* 获取关键字位置坐标
* @param pdfIn pdf文件byte流
* @param keyWord 关键字
* @return 位置信息列表 [0]:x [1]:y [2]页数
* @throws Exception
*/
public List getPosition(byte[] pdfIn, String keyWord) throws Exception {
List list = new ArrayList();
PdfReader pdfReader = new PdfReader(pdfIn);
int numberOfPages = pdfReader.getNumberOfPages();
PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);
for (i = 1; i <= numberOfPages; i++) {
pdfReaderContentParser.processContent(i, new RenderListener() {
@Override
public void renderText(TextRenderInfo textRenderInfo) {
String text = textRenderInfo.getText(); // 整页内容
if (null != text && text.contains(keyWord)) {
Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();
float[] arr = new float[3];
arr[0] = boundingRectange.x;
arr[1] = boundingRectange.y;
arr[2] = i;
list.add(arr);
}
}
@Override
public void renderImage(ImageRenderInfo arg0) {
}
@Override
public void endTextBlock() {
}
@Override
public void beginTextBlock() {
}
});
}
return list;
}
5 签章签名填充日期换页时位置调整
/**
*
* @param pageSet 文件byte流
* @param position 页数 x y
* @return
* @throws IOException
* @throws DocumentException
*/
public static byte[] fillDate(byte[] pageSet,List<Float> position) throws IOException, DocumentException {
//盖章日期填充偏移量 签名与日期同页偏移
float y = -40f;
float x = 0f;
//判断是否翻页标志位
float index = 73;
File modelFile = new File(System.getProperty("user.dir"));
if (!modelFile.exists()) {
modelFile.mkdirs();
}
String nowDate = LocalDate.now().toString();
PdfReader reader = new PdfReader(pageSet);
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir") + "/" + nowDate + ".pdf");
PdfStamper stamper = new PdfStamper(reader,fos);
Integer pageNum = Integer.parseInt(position.get(2).toString());
String xPos = position.get(0).toString();
String yPos = position.get(1).toString();
//签名与日期分页时特殊处理 ,如间距更大需继续特殊处理
if (java.lang.Float.parseFloat(yPos) < index) {
pageNum++;
// 第一行:68 (729)第二行56 (711)第三行44(723)
if(java.lang.Float.parseFloat(yPos)<74&& java.lang.Float.parseFloat(yPos)>60){
y = 729;
}else if(java.lang.Float.parseFloat(yPos)<60&& java.lang.Float.parseFloat(yPos)>52){
y= 711;
}else if (java.lang.Float.parseFloat(yPos)<48&& java.lang.Float.parseFloat(yPos)>40){
y = 723;
}
}
PdfContentByte pdfContentByte = stamper.getOverContent(pageNum);
pdfContentByte.beginText();
// 设置字体及字号
pdfContentByte.setColorFill(BaseColor.DARK_GRAY);
pdfContentByte.setFontAndSize(BaseFont.createFont(), 10);
pdfContentByte.showTextAligned(Element.ALIGN_LEFT, nowDate,
java.lang.Float.parseFloat(xPos) + x, y+ java.lang.Float.parseFloat(yPos), 0);
pdfContentByte.endText();
stamper.close();
// 将输出流关闭
fos.close();
reader.close();
File file = new File(System.getProperty("user.dir") + "/" + nowDate+ ".pdf");
byte[] outputStream = FileCopyUtils.copyToByteArray(file);
delFile(file);
return outputStream;
}
public static void delFile(File file) {
if (file.exists() && file.isFile()) {
file.delete();
}
}
6.PDF模板数据填充
pom依赖
<dependency>
<groupId>freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.9</version>
</dependency>
/**
*
* @param param 填充参数
* @param bytes 待文件文件流
* @param fileName 文件名
* @return
* @throws Exception
*/
public static String processHtmlParam(Map param,byte[] bytes,String fileName) throws Exception {
File modelFile = new File(System.getProperty("user.dir"));
if (!modelFile.exists()) {
modelFile.mkdirs();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(System.getProperty("user.dir") + "/" + fileName);
fos.write(bytes);
}catch (Exception e) {
System.out.println("文件写入失败 : " + e.getMessage());
} finally {
if ( null!=fos ) {
fos.close();
}
}
Configuration config = new Configuration();
config .setDirectoryForTemplateLoading(modelFile);
config .setObjectWrapper(new DefaultObjectWrapper());
config .setDefaultEncoding("UTF-8");
config .setClassicCompatible(true);
Template template = config .getTemplate(fileName);
StringWriter stringWriter = new StringWriter();
BufferedWriter writer = new BufferedWriter(stringWriter);
template.process(param, writer);
String htmlStr = stringWriter.toString();
writer.flush();
writer.close();
delFile(System.getProperty("user.dir"),fileName);
return htmlStr;
}
7.将字符串转换为PDF
/**
* 根据html字符串内容生成pdf
*
* @param pdfFilePath pdf文件存储位置
* @param htmlcontent html内容
*/
public static void parseHtml2PdfByString(String pdfFilePath, String htmlcontent) throws Exception{
Document document = new Document();
PdfWriter writer = null;
try {
writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath));
// 设置底部距离60,解决重叠问题
document.setPageSize(PageSize.A4);
document.setMargins(50, 45, 50, 60);
document.setMarginMirroring(false);
document.open();
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmlcontent.getBytes("UTF-8")), null, Charset
.forName("UTF-8"), new MyFontProvider("C:\\Users\\rw\\Desktop\\ss.ttf"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != document) {
document.close();
}
if (null != writer) {
writer.close();
}
}
}
未完待续…