前言

你好呀,我是小邹。

昨天给大家分享了PDF文件添加水印后保存,今天再来聊一聊如何实现印章、签名

“Talk is cheap,show me the code.”

效果

实现

① 添加相关依赖

<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>

② 工具类PdfUtil

package top.hqxiaozou.utils;import top.hqxiaozou.entity.PdfAddContentParam;
import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;/*** @author:邹祥发* @date:2022/11/24 10:19* @description:PDF工具类,提供 水印、签名、盖章 功能*/
@Slf4j
public class PdfUtil {/*** 往PDF上添加文字水印** @param inputFile     原文件* @param outputFile    加水印后的文件* @param waterMarkName 水印字符*/public static void addWaterMark(String inputFile, String outputFile, String waterMarkName) {PdfReader reader = null;PdfStamper stamper = null;try {reader = new PdfReader(inputFile);stamper = new PdfStamper(reader, Files.newOutputStream(Paths.get(outputFile)));//水印字体,放到服务器上对应文件夹下(arial中文不生效)//BaseFont base = BaseFont.createFont("D:/workspace/springboot/src/main/resources/arial.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);Rectangle pageRect;PdfGState gs = new PdfGState();//填充不透明度  为1完全不透明gs.setFillOpacity(0.1f);//笔画不透明度, 为1完全不透明gs.setStrokeOpacity(0.1f);int total = reader.getNumberOfPages() + 1;JLabel label = new JLabel();FontMetrics metrics;int textH;int textW;label.setText(waterMarkName);metrics = label.getFontMetrics(label.getFont());textH = metrics.getHeight();textW = metrics.stringWidth(label.getText());PdfContentByte under;int interval = 0;for (int i = 1; i < total; i++) {pageRect = reader.getPageSizeWithRotation(i);//在字体下方加水印under = stamper.getOverContent(i);under.beginText();under.saveState();under.setGState(gs);//这里修改水印字体大小under.setFontAndSize(base, 36);//这里设置字体上下间隔for (int height = interval + textH; height < pageRect.getHeight(); height = height + textH * 9) {//这里设置字体左右间隔for (int width = interval + textW; width < pageRect.getWidth() + textW; width = width + textW * 4) {//这里设置倾斜角度under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, 45);}}under.endText();}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();} finally {try {if (stamper != null) {stamper.close();}} catch (IOException | com.itextpdf.text.DocumentException e) {e.printStackTrace();}if (reader != null) {reader.close();}}}/*** 根据指定坐标往PDF上添加文字内容** @param filePath            原文件路径* @param pdfAddContentParams 实体类*/public static byte[] addText(String filePath, List<PdfAddContentParam> pdfAddContentParams) throws Exception {PdfReader pdfReader = new PdfReader(filePath);ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//设置输入文件以及输出文件地址PdfStamper stamper = new PdfStamper(pdfReader, byteArrayOutputStream);//设置字体BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);for (PdfAddContentParam pdfAddContentParam : pdfAddContentParams) {Font font = new Font(baseFont, 10);if (pdfAddContentParam.getPageNum() > pdfReader.getNumberOfPages()) {log.error("设置的页码数[" + pdfAddContentParam.getPageNum() + "]大于原文件页码数[" + pdfReader.getNumberOfPages() + "]!请重新输入");throw new RuntimeException("设置的页码数[" + pdfAddContentParam.getPageNum() + "]大于原文件页码数[" + pdfReader.getNumberOfPages() + "]!请重新输入");}PdfContentByte overContent = stamper.getOverContent(pdfAddContentParam.getPageNum());ColumnText columnText = new ColumnText(overContent);columnText.setSimpleColumn(pdfAddContentParam.getLlx(), pdfAddContentParam.getLly(), pdfAddContentParam.getUrx(), pdfAddContentParam.getUry());Paragraph elements = new Paragraph(pdfAddContentParam.getContent());elements.setFont(font);columnText.addElement(elements);columnText.go();}stamper.close();return byteArrayOutputStream.toByteArray();}/*** 根据关键字往PDF上添加文字内容** @param filePath            原文件路径* @param pdfAddContentParams 实体类*/public static byte[] addTextByKeyword(String filePath, List<PdfAddContentParam> pdfAddContentParams) throws Exception {PdfReader pdfReader = new PdfReader(filePath);ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//设置输入文件以及输出文件地址PdfStamper stamper = new PdfStamper(pdfReader, byteArrayOutputStream);// 获取PDF文件的总页数int pageNum = pdfReader.getNumberOfPages();PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);for (PdfAddContentParam pdfAddContentParam : pdfAddContentParams) {StringBuilder stringBuilder = new StringBuilder();final boolean[] hasKeyword = {false, true};String keyword = pdfAddContentParam.getKeyword();int length = keyword.length();if (length == 0) {throw new RuntimeException("请输入关键字!");}for (int page = 1; page <= pageNum; page++) {if (hasKeyword[0]) {break;}int finalPage = page;pdfReaderContentParser.processContent(page, new RenderListener() {@Overridepublic void beginTextBlock() {}@SneakyThrows@Overridepublic void renderText(TextRenderInfo renderInfo) {// 读取PDF文件的内容String text = renderInfo.getText().trim();stringBuilder.append(text);if (stringBuilder.toString().contains(keyword)) {Rectangle2D.Float boundingRectangle = renderInfo.getBaseline().getBoundingRectange();if (hasKeyword[1]) {// 关键字的坐标double x = boundingRectangle.getX();double y = boundingRectangle.getY();//设置字体BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);Font font = new Font(baseFont, 10);PdfContentByte overContent = stamper.getOverContent(finalPage);ColumnText columnText = new ColumnText(overContent);// 根据关键字的坐标计算+偏移量得到批注字体的坐标columnText.setSimpleColumn((float) x + pdfAddContentParam.getLlx(), (float) y + pdfAddContentParam.getLly(), (float) x + 100 + pdfAddContentParam.getUrx(), (float) y + pdfAddContentParam.getUry());Paragraph elements = new Paragraph(pdfAddContentParam.getContent());elements.setFont(font);columnText.addElement(elements);columnText.go();hasKeyword[1] = false;}hasKeyword[0] = true;}if (stringBuilder.toString().length() > length * 3) {stringBuilder.setLength(0);}}@Overridepublic void endTextBlock() {}@Overridepublic void renderImage(ImageRenderInfo renderInfo) {}});}}stamper.close();pdfReader.close();return byteArrayOutputStream.toByteArray();}/*** pdf插入图片** @param oldPath 插入图片前的路径* @param newPath 插入图片后的路径* @param imgPath 图片路径* @throws IOException* @throws DocumentException*/public static void addImage(String oldPath, String newPath, String imgPath) throws IOException, DocumentException {InputStream inputStream = Files.newInputStream(Paths.get(oldPath));FileOutputStream out = new FileOutputStream(newPath);PdfReader reader = new PdfReader(inputStream);//pdf页数int pdfPages = reader.getNumberOfPages();PdfStamper stamper = new PdfStamper(reader, out);//图片BufferedImage bufferedImage = ImageIO.read(Files.newInputStream(Paths.get(imgPath)));//x轴坐标int x = 350;//y轴坐标int y = 20;//图片放置的页码for (int i = pdfPages; i <= pdfPages; i++) {//图片处理Image img = Image.getInstance(ImageUtil.imageToBytes((bufferedImage), "png"));//设置图片大小img.scaleAbsolute(192, 100);img.setTransparency(new int[0]);//设置图片位置img.setAbsolutePosition(x, y);stamper.getOverContent(i).addImage(img);}//关闭资源stamper.close();out.close();reader.close();}
}

③ 工具类ImageUtil

package top.hqxiaozou.utils;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;/*** @author:邹祥发* @date:2022/11/25 14:14* @description:转换BufferedImage数据为byte数组*/
public class ImageUtil {/*** 转换BufferedImage 数据为byte数组** @param image  Image对象* @param format image格式字符串.如"gif","png"* @return byte数组*/public static byte[] imageToBytes(BufferedImage image, String format) {ByteArrayOutputStream out = new ByteArrayOutputStream();try {ImageIO.write(image, format, out);} catch (IOException e) {e.printStackTrace();}return out.toByteArray();}/*** 转换byte数组为Image** @param bytes* @return Image*/public static Image bytesToImage(byte[] bytes) {Image image = Toolkit.getDefaultToolkit().createImage(bytes);try {MediaTracker mt = new MediaTracker(new Label());mt.addImage(image, 0);mt.waitForAll();} catch (InterruptedException e) {e.printStackTrace();}return image;}
}

④ 实体类

package top.hqxiaozou.entity;import lombok.Data;/*** @author:邹祥发* @date:2022/11/25 10:36* @description:pdf添加签名实体类*/
@Data
public class PdfAddContentParam {/***  要添加的文字*/private String content;/*** 页码*/private Integer pageNum;/*** 关键字*/private String keyword;/*** 文本框坐标(左下角x,y,右上角x,y)*/private Float llx;private Float lly;private Float urx;private Float ury;public PdfAddContentParam() {}public PdfAddContentParam(String content, Integer pageNum, Float llx, Float lly, Float urx, Float ury) {this.content = content;this.pageNum = pageNum;this.llx = llx;this.lly = lly;this.urx = urx;this.ury = ury;}public PdfAddContentParam(String content, String keyword, Float llx, Float lly, Float urx, Float ury) {this.content = content;this.keyword = keyword;this.llx = llx;this.lly = lly;this.urx = urx;this.ury = ury;}
}

⑤ 测试类

  • 添加水印
package top.hqxiaozou.test;import top.hqxiaozou.utils.PDFUtils;/*** @author:邹祥发* @date:2022/11/24 10:41* @description:PDF水印测试类*/
public class AddWaterMarkTest {public static void main(String[] args) {PDFUtils.addWaterMark("C:/Users/zou/Desktop/阿里巴巴Java开发手册(终极版).pdf", "C:/Users/zou/Desktop/new.pdf", "https://www.hqxiaozou.top");}
}
  • 插入图片
package top.hqxiaozou.pdf;import top.hqxiaozou.utils.PdfUtil;
import com.itextpdf.text.DocumentException;import java.io.IOException;/*** @author:邹祥发* @date:2022/11/25 14:22* @description:pdf插入图片测试类*/
public class AddImageTest {public static void main(String[] args) {try {PdfUtil.addImage("C:/Users/zou/Desktop/watermark.pdf", "C:/Users/zou/Desktop/image.pdf", "C:/Users/zou/Desktop/sign.bmp");} catch (IOException | DocumentException e) {throw new RuntimeException(e);}}
}
  • 根据指定坐标往PDF添加文字
package top.hqxiaozou.pdf;import top.hqxiaozou.entity.PdfAddContentParam;
import top.hqxiaozou.utils.PdfUtil;import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;/*** @author:邹祥发* @date:2022/11/24 20:30* @description:根据指定坐标往PDF添加文字内容测试类*/
public class AddTextTest {public static void main(String[] args) {// 按坐标添加批注PdfAddContentParam name = new PdfAddContentParam("召田最帅boy", 3, 415F, 36F, 610F, 83F);List<PdfAddContentParam> pdfAddContentParams = new ArrayList<>();Collections.addAll(pdfAddContentParams, name);byte[] bytes;try {bytes = PdfUtil.addText("C:/Users/zou/Desktop/image.pdf", pdfAddContentParams);Files.newOutputStream(Paths.get("C:/Users/zou/Desktop/sign.pdf")).write(bytes);} catch (Exception e) {throw new RuntimeException(e);}}
}
  • 根据关键字往PDF添加文字
package top.hqxiaozou.pdf;import top.hqxiaozou.entity.PdfAddContentParam;
import top.hqxiaozou.utils.PdfUtil;import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;/*** @author:邹祥发* @date:2022/11/25 11:16* @description:根据关键字往PDF添加文字内容测试类*/
public class AddTextByKeywordTest {public static void main(String[] args) {// 按关键字批注PdfAddContentParam keyword = new PdfAddContentParam("test", "召田最帅boy", 1F, 2F, 3F, 40F);List<PdfAddContentParam> pdfAddContentParams = new ArrayList<>();Collections.addAll(pdfAddContentParams, keyword);byte[] bytes;try {bytes = PdfUtil.addTextByKeyword("C:/Users/zou/Desktop/target.pdf", pdfAddContentParams);Files.newOutputStream(Paths.get("C:/Users/zou/Desktop/new.pdf")).write(bytes);} catch (Exception e) {throw new RuntimeException(e);}}
}

Java实现给PDF文件加水印、图片、签名(含测试类)相关推荐

  1. 咖啡汪日志——JAVA导出pdf文件加水印 文字+图片、文字

    咖啡汪日志--JAVA导出pdf文件加水印 文字和图片.文字 hello,又大家见面了! 作为一只不是在戏精就是在戏精路上的哈士奇,今天要展示给大家的就是如何快捷地给pdf文件增加各种水印.嗷呜呜,前 ...

  2. Java实现给PDF文件加文字水印和图片水印(可以自定义水印格式)

    使用Java代码给PDF文件加文字水印 直接上代码运行即可 依赖 有的可能用不上我直接复制全部了 <dependencies><!--word文件转PDF以及水印-->< ...

  3. pdf文件加水印怎么加,5个方法快速易学

    PDF文件加水印是一个非常重要且常见的操作,对于不熟悉这一技能的人来说可能会感到困难.这也是为什么在某些浏览器中"pdf文件加水印怎么加"搜索量可高达几百万之多.但是,我们都知道掌 ...

  4. vue 中利用canvas 给pdf文件加水印---详细教程(附上完整代码)

    需求:在h5网页中打开pdf文件,要求给文件添加水印 实现技术及插件:vue,vue-pdf,canvas 插件安装: npm i vue-pdf --save npm i pdf-lib --sav ...

  5. Java代码给csv文件加水印_如何给CSV数据包的图片批量加上水印

    批量加水印要用到加水印的工具了吧 一.发布产品的时候,你的图片传到网上去的时候,都有一个选项,是否要在图片上加水印,系统默认的都是加水印的,你只要不选否,都是加了的. 二.photoshop加水印 1 ...

  6. Java代码给csv文件加水印_闪电PDF虚拟打印机如何给文件加上水印?

    闪电PDF虚拟打印机如何给文件加上水印?专业的虚拟打印机,该软件将doc.txt.jpg等多种格式文档输出为PDF格式文件,而接下来的文章中介绍的则是使用该软件将需要打印的文件添加水印的方法,有需要的 ...

  7. 如何使用python给PDF文件加水印

    Python作为编程界最火的语言,能做的事几乎你能想到的它都能干,就连抢茅台都可以,还有什么不行?! Python作为脚本编程语言,可以做很多事情.使用Python,你可以轻松地给pdf加上水印. 你 ...

  8. Java代码给csv文件加水印_如何给文件加上水印?

    如何给文件加上水印? 修改日期:2020-07-31 11:33:48 这是一款专业的虚拟打印机,使用本软件几乎可以把任何windows程序文件通过打印驱动打印成PDF文件.可以快速将doc.txt. ...

  9. iText包对每页pdf文件加水印

    https://ishare.iask.sina.com.cn/f/31zwqlKmIwM.html

  10. PDF.js对打印、下载按钮做限制,pdf文件加水印

最新文章

  1. python做数据分析的包_用Python做数据分析,Numpy,Pandas,matp
  2. App相互唤醒的几种方式
  3. python语句分为什么_Python为什么使用缩进来分组语句?
  4. mosek 安装配置python_Windows系统Python解释器的安装配置
  5. Linux echo print命令,linux常用命令-echo/printf/file
  6. HTML5格式问题,你遇到了吗?
  7. android 函数式编程,响应式编程在Android中的应用
  8. python之词频统计
  9. 风险预测模型_利用好预后预测模型,2个月发篇4分+SCI不是梦
  10. 操作系统核心与驱动程序
  11. Codeforces 32C.Flea
  12. 【英雄九日集训】(七月第一轮)第一天——数组
  13. CAS的ABA问题,ABA问题会导致什么后果?
  14. 1. (3.20~5.5)2022年自动化保研信息+分析汇总(夏令营)
  15. C#(Winform)程序无法使用Windows Media Player 组件播放视频文件
  16. 企业网站[正能量系列]失业的程序员(一)
  17. 微信公众平台登陆小程序后,在 开发-开发者工具 下,找不到 腾讯云
  18. 抽象类能实例化吗?——口气很强硬——“不能”(详解)
  19. VAR模型与BP神经网络算法的简单实践
  20. 通信技术-网络的类别

热门文章

  1. c语言模拟洪泛路由算法,[Angular, TypeScript, 路由算法] 模拟IP层路由协议,实现LS算法、洪泛算法、DV算法、路由毒化...
  2. adb shell error: device offline
  3. Rclone挂载SharePoint
  4. OpenBSD 6.8 切换到国内镜像源的一种临时方法:声明PKG_PATH
  5. 【Golang】JSON Marshal Unmarshal
  6. 无监督降维 效果评价 trustworthiness measure
  7. Ubuntu 命令行 安装 Operator Mono 字体
  8. Linux选择填空练习题
  9. 局域网传输文件详解(转)
  10. 记:疯狂的程序员 (连续n天写n个代码)