Java实现给PDF文件加水印、图片、签名(含测试类)
生活随笔
收集整理的這篇文章主要介紹了
Java实现给PDF文件加水印、图片、签名(含测试类)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
你好呀,我是小鄒。
昨天給大家分享了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;} }⑤ 測試類
- 添加水印
- 插入圖片
- 根據指定坐標往PDF添加文字
- 根據關鍵字往PDF添加文字
總結
以上是生活随笔為你收集整理的Java实现给PDF文件加水印、图片、签名(含测试类)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用PageOffice实现文档(wor
- 下一篇: SANGFOR产品笔记