怎么做视频平台网站吗,东莞附近公司做网站建设多少钱,网站创建方案怎么写,网站怎样快速排名作者#xff1a;fyupeng 技术专栏#xff1a;☞ https://github.com/fyupeng 项目地址#xff1a;☞ https://github.com/fyupeng/distributed-blog-system-api 留给读者 一、介绍
根据关键字偏移量水印签字。
允许重复调用#xff0c;文件安全性高#xff0c;自动备份并… 作者fyupeng 技术专栏☞ https://github.com/fyupeng 项目地址☞ https://github.com/fyupeng/distributed-blog-system-api 留给读者 一、介绍
根据关键字偏移量水印签字。
允许重复调用文件安全性高自动备份并恢复。
二、代码
测试 Demo PdfUtilTest .java package com.gwssi.common.service;import com.gwssi.common.util.PDFSigner;
import com.gwssi.torch.v1.dao.TorchDaoManager;
import com.gwssi.torch.v1.dao.api.IBaseDao;
import org.apache.commons.lang.StringUtils;import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Auther: fyp* Date: 2024/6/24* Description:* Package: com.gwssi.common.service* Version: 1.0*/
public class PdfUtilTest {public String signPdf(String applyno) {String[] keywords {领取人签字, 发照日期, 领取日期};Float[] signatureTextOffsetX {0f ,100f, -20f};Float[] signatureTextOffsetY {-50f, 0f, -50f};//String[] signatureTexts {小明, 2024-04-26, 2024-04-28};ListString signatureTexts new ArrayList();String filepath C:/output.pdf;MapString,Object signatureParams new HashMap();signatureParams.put(keywords, keywords);signatureParams.put(signatureTexts, signatureTexts);signatureParams.put(signatureTextOffsetX, signatureTextOffsetX);signatureParams.put(signatureTextOffsetY, signatureTextOffsetY);PDFSigner.signPdf(filepath, signatureParams, Color.gray, 18);return filepath;}}
封装类 PDFSigner.java
package com.gwssi.common.util;/*** Auther: fyp* Date: 2024/4/28* Description:* Package: com.gwssi.common.util* Version: 1.0*/
import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.text.PDFTextStripper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class PDFSigner {private static final Logger LOG LoggerFactory.getLogger(PDFSigner.class);private static String filePath;private static ResourceBundle resourceBundle;static {resourceBundle ResourceBundle.getBundle(torch-v1);filePath resourceBundle.getString(project.filePath);}//private static final Properties properties System.getProperties();// 获取当前用户的工作目录//private static final String userDir properties.getProperty(user.dir);//private static final String rootDirPath userDir /WebContent/;public static byte[] readFileToBytes(File file) throws IOException {FileInputStream fis new FileInputStream(file);byte[] bytes new byte[(int) file.length()];fis.read(bytes);fis.close();return bytes;}public static void backPdf(String pdfPath) {// 文件 备份String backPdfPath pdfPath .bak;try {File file new File(pdfPath);byte[] fileBytes null;try {if (checkFileSign(pdfPath, backPdfPath)) {fileBytes readFileToBytes(file);backFile(fileBytes, backPdfPath);}} catch (Exception e) {LOG.error(文件备份异常失败原因{}, e.getMessage(), e);throw new RuntimeException(文件备份异常失败原因 e.getMessage());}} catch (Exception e) {LOG.error(文件备份异常失败原因{}, e.getMessage(), e);throw new RuntimeException(文件备份异常失败原因 e.getMessage());}}public static void signPdf(String pdfPath, MapString ,Object signParams, Color signatureColor, int signatureFontSize) {String[] keywords (String[]) signParams.get(keywords);ListString signatureTexts (ListString) signParams.get(signatureTexts);Float[] signatureTextOffsetX (Float[]) signParams.get(signatureTextOffsetX);Float[] signatureTextOffsetY (Float[]) signParams.get(signatureTextOffsetY);// 文件 备份String backPdfPath pdfPath .bak;File file new File(pdfPath);byte[] fileBytes null;try {if (checkFileSign(pdfPath, backPdfPath)) {fileBytes readFileToBytes(file);backFile(fileBytes, backPdfPath);} else {fileBytes readFileToBytes(file);}PDDocument document PDDocument.load(new File(pdfPath));for (int idx 0; idx keywords.length; idx) {ListKeyWordPosition keyWordsByByte PdfMatchKeyword.getKeyWordsByByte(fileBytes, keywords[idx]);System.out.println(keyWordsByByte);float[] keyWordsByByte2 PdfHelper.getKeyWordsByByte(fileBytes, keywords[idx]);float signatureX keyWordsByByte2[0]; // 使用关键字的 x 坐标作为签名的 x 坐标float signatureY keyWordsByByte2[1] ; // 在关键字的 y 坐标上移 20 个单位作为签名的 y 坐标int pageNum findKeywordPage(document, keywords[idx]);if (pageNum ! -1) {signPage(document, pageNum, signatureTexts.get(idx), signatureX signatureTextOffsetX[idx], signatureY signatureTextOffsetY[idx], signatureColor, signatureFontSize);// PDF 覆盖 (原文件备份)document.save(pdfPath);System.out.println(PDF 文件签名成功);} else {System.out.println(未找到关键字无法签名。);}}document.close();//deleteFile(pdfPath);} catch (Exception e) {LOG.error(文件备份异常失败原因{}, e.getMessage(), e);throw new RuntimeException(文件备份异常失败原因 e.getMessage());}}public static byte[] fileToBytes(File file) throws IOException {// 创建字节输入流FileInputStream fis new FileInputStream(file);try {// 获取文件大小long fileSize file.length();// 创建一个与文件大小相同的字节数组byte[] bytesArray new byte[(int) fileSize];// 将文件内容读取到字节数组fis.read(bytesArray);// 返回字节数组return bytesArray;} finally {// 关闭文件输入流fis.close();}}/**** 检查是否第一次生成 第一次 true* param pdfPath* param backPdfPath* return* throws IOException*/private static boolean checkFileSign(String pdfPath, String backPdfPath) throws IOException {File pdfFile new File(pdfPath);File backPDFFile new File(backPdfPath);// 恢复文件 重新生成 (存在备份文件非第一次生成)if (backPDFFile.exists()) {if (pdfFile.exists()) {pdfFile.delete();}byte[] bytes fileToBytes(backPDFFile);FileOutputStream fos new FileOutputStream(pdfFile);fos.write(bytes);fos.close();return false;}// 第一次生成return true;}private static void backFile(byte[] fileBytes, String backPdfPath) throws IOException {File file new File(backPdfPath);FileOutputStream fos new FileOutputStream(file);fos.write(fileBytes);fos.close();}private static void deleteFile(String pdfPath) throws IOException {File file new File(pdfPath);file.delete();}public static void main(String[] args) throws FileNotFoundException {String[] keywords {领取人签字, 发照日期, 领取日期};Float[] signatureTextOffsetX {0f ,100f, -20f};Float[] signatureTextOffsetY {-50f, 0f, -50f};String[] signatureTexts {小明, 2024-04-26, 2024-04-28};MapString,Object signatureParams new HashMap();signatureParams.put(keywords, keywords);signatureParams.put(signatureTexts, signatureTexts);signatureParams.put(signatureTextOffsetX, signatureTextOffsetX);signatureParams.put(signatureTextOffsetY, signatureTextOffsetY);signPdf(D:/doc/2023-10-13/14-37-37/珠海陈文路走走杨服装零售店(440003A2300006440).pdf, signatureParams, Color.gray, 18);}public static int findKeywordPage(PDDocument document, String keyword) throws IOException {PDFTextStripper stripper new PDFTextStripper();int pageNum 0;for (PDPage page : document.getPages()) {stripper.setStartPage(pageNum 1);stripper.setEndPage(pageNum 1);String text stripper.getText(document);if (text.contains(keyword)) {return pageNum;}pageNum;}return -1;}public static void signPage(PDDocument document, int pageNum, String signatureText, float signatureX, float signatureY, Color signatureColor, int fontSize) throws IOException {PDPage page document.getPage(pageNum);try (PDPageContentStream contentStream new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true)) {contentStream.beginText();//PDFont font PDType0Font.load(document, new File(filePath, /app/font/simsun.ttf)); // 替换成实际的字体文件路径//PDFont font PDType0Font.load(document, new File(filePath, /app/font/STSong.ttf)); // 替换成实际的字体文件路径//PDFont font PDType0Font.load(document, new File(filePath, /app/font/simhei.ttf)); // 替换成实际的字体文件路径PDFont font PDType0Font.load(document, new File( filePath /app/font/hanyizhonghei.ttf)); // 替换成实际的字体文件路径contentStream.setFont(font, fontSize);contentStream.setNonStrokingColor(signatureColor); // 设置文本颜色contentStream.newLineAtOffset(signatureX, signatureY); // 垂直偏移量减少签字下移contentStream.showText(signatureText);contentStream.endText();} catch (Exception e) {LOG.error(签名异常异常原因{}, e.getMessage(), e);throw new RuntimeException(签名异常异常原因 e.getMessage());}}}
PdfMatchKeyword.java package com.gwssi.common.util;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import com.itextpdf.text.pdf.parser.Vector;public class PdfMatchKeyword {/*** 用于供外部类调用获取关键字所在PDF文件坐标* param filepath* param keyWords* return*/public static ListKeyWordPosition getKeyWordsByPath(String filepath, String keyWords) {ListKeyWordPosition matchItems null;try{PdfReader pdfReader new PdfReader(filepath);matchItems getKeyWords(pdfReader, keyWords);} catch (IOException e) {e.printStackTrace();}return matchItems;}/*** 用于供外部类调用获取关键字所在PDF文件坐标* param filepath* param keyWords* return*/public static ListKeyWordPosition getKeyWordsByByte(byte[] pdfIn, String keyWords) {ListKeyWordPosition matchItems null;try{PdfReader pdfReader new PdfReader(pdfIn);matchItems getKeyWords(pdfReader, keyWords);} catch (IOException e) {e.printStackTrace();}return matchItems;}/*** 获取关键字所在PDF坐标* param pdfReader* param keyWords* return*/private static ListKeyWordPosition getKeyWords(PdfReader pdfReader, String keyWords) {int page 0;ListKeyWordPosition matchItems new ArrayList();try{int pageNum pdfReader.getNumberOfPages();StringBuilder allText null;//遍历页for (page 1; page pageNum; page) {//只记录当页的所有内容需要记录全部页放在循环外面ListItemPosition allItems new ArrayList();//扫描内容MyTextExtractionStrategy myTextExtractionStrategy new MyTextExtractionStrategy(allItems, page);PdfTextExtractor.getTextFromPage(pdfReader, page, myTextExtractionStrategy);//当页的文字内容用于关键词匹配allText new StringBuilder();//一个字一个字的遍历for (int i0; iallItems.size(); i) {ItemPosition item allItems.get(i);allText.append(item.getText());//关键字存在连续多个块中if(allText.indexOf(keyWords) ! -1) {KeyWordPosition keyWordPosition new KeyWordPosition();//记录关键词每个字的位置只记录开始结束标记时会有问题ListItemPosition listItem new ArrayList();for(int ji-keyWords.length()1; ji; j) {listItem.add(allItems.get(j));}keyWordPosition.setListItem(listItem);keyWordPosition.setText(keyWords);matchItems.add(keyWordPosition);allText.setLength(0);}}}} catch (Exception e) {e.printStackTrace();}return matchItems;}/*** 添加矩形标记* param oldPath* param newPath* param matchItems 关键词* param color 标记颜色* param lineWidth 线条粗细* param padding 边框内边距* throws DocumentException* throws IOException*/public static void andRectangleMark(String oldPath, String newPath, ListKeyWordPosition matchItems, BaseColor color, int lineWidth, int padding) throws DocumentException, IOException{// 待加水印的文件PdfReader reader new PdfReader(oldPath);// 加完水印的文件PdfStamper stamper new PdfStamper(reader, new FileOutputStream(newPath));PdfContentByte content;// 设置字体// 循环对每页插入水印for (KeyWordPosition keyWordPosition:matchItems){//一个关键词的所有字坐标ListItemPosition oneKeywordItems keyWordPosition.getListItem();for(int i0; ioneKeywordItems.size(); i) {ItemPosition item oneKeywordItems.get(i);ItemPosition preItem i0?null:oneKeywordItems.get(i-1);// 水印的起始content stamper.getOverContent(item.getPage());// 开始写入水印content.setLineWidth(lineWidth);content.setColorStroke(color);//底线content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getRight()padding, item.getRectangle().getBottom()-padding);if(i!0 preItem!null (preItem.getRectangle().getBottom()-padding)(item.getRectangle().getBottom()-padding) (preItem.getRectangle().getRight()padding)!(item.getRectangle().getLeft()-padding)) {content.moveTo(preItem.getRectangle().getRight()padding, preItem.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);}//上线content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()padding);content.lineTo(item.getRectangle().getRight()padding, item.getRectangle().getTop()padding);if(i!0 preItem!null (preItem.getRectangle().getTop()padding)(item.getRectangle().getTop()padding) (preItem.getRectangle().getRight()padding)!(item.getRectangle().getLeft()-padding)) {content.moveTo(preItem.getRectangle().getRight()padding, preItem.getRectangle().getTop()padding);content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()padding);}//左线if(i0) {content.moveTo(item.getRectangle().getLeft()-padding, item.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getLeft()-padding, item.getRectangle().getTop()padding);}//右线if(i(oneKeywordItems.size()-1)) {content.moveTo(item.getRectangle().getRight()padding, item.getRectangle().getBottom()-padding);content.lineTo(item.getRectangle().getRight()padding, item.getRectangle().getTop()padding);}content.stroke();}}stamper.close();}public static void main(String[] args) throws Exception {String keyword 陈雪英;String sourcePdf D:\\SoftPackage\\InterDowloads\\东莞市浩影塑胶模具科技有限公司-登记审核表.pdf;String watermarkPdf D:\\SoftPackage\\InterDowloads\\东莞市浩影塑胶模具科技有限公司-登记审核表2.pdf;Long start System.currentTimeMillis();System.out.println(开始扫描....);ListKeyWordPosition matchItems getKeyWordsByPath(sourcePdf, keyword);System.out.println(扫描结束[(System.currentTimeMillis()-start)ms]共找到关键字[keyword]出现[matchItems.size()]次);start System.currentTimeMillis();System.out.println(开始添加标记....);andRectangleMark(sourcePdf, watermarkPdf, matchItems, BaseColor.RED, 2, 2);System.out.println(标记添加完成[(System.currentTimeMillis()-start)ms]);}
}/*** ClassName: MyTextExtractionStrategy* Description: 记录所有位置字体信息这种方式获取坐标信息和字体信息方便一点* author chenyang-054* date 2021-04-09 11:00:31*/
class MyTextExtractionStrategy implements TextExtractionStrategy{private ListItemPosition positions;private Integer page;public MyTextExtractionStrategy() {}public MyTextExtractionStrategy(ListItemPosition positions, Integer page) {this.positions positions;this.page page;}Overridepublic void beginTextBlock() {// TODO Auto-generated method stub}Overridepublic void renderText(TextRenderInfo renderInfo) {ItemPosition ItemPosition new ItemPosition();Vector bottomLeftPoint renderInfo.getDescentLine().getStartPoint();Vector topRightPoint renderInfo.getAscentLine().getEndPoint();//记录矩形坐标Rectangle rectangle new Rectangle(bottomLeftPoint.get(Vector.I1), bottomLeftPoint.get(Vector.I2),topRightPoint.get(Vector.I1), topRightPoint.get(Vector.I2));ItemPosition.setPage(page);ItemPosition.setRectangle(rectangle);ItemPosition.setText(renderInfo.getText());positions.add(ItemPosition);}Overridepublic void endTextBlock() {// TODO Auto-generated method stub}Overridepublic void renderImage(ImageRenderInfo renderInfo) {// TODO Auto-generated method stub}Overridepublic String getResultantText() {// TODO Auto-generated method stubreturn null;}
}
PdfHelper .java
package com.gwssi.common.util;import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;import java.io.IOException;/*** ClassName PdfHelper* Description Pdf帮助类* Author AlphaJunS* Date 2020/3/7 17:40* Version 1.0*/
public class PdfHelper {/*** Author AlphaJunS* Date 18:24 2020/3/7* Description 用于供外部类调用获取关键字所在PDF文件坐标* param filepath* param keyWords* return float[]*/public static float[] getKeyWordsByPath(String filepath, String keyWords) {float[] coordinate null;try{PdfReader pdfReader new PdfReader(filepath);coordinate getKeyWords(pdfReader, keyWords);} catch (IOException e) {e.printStackTrace();}return coordinate;}public static float[] getKeyWordsByByte(byte[] pdfin, String keyWords) {float[] coordinate null;try{PdfReader pdfReader new PdfReader(pdfin);coordinate getKeyWords(pdfReader, keyWords);} catch (IOException e) {e.printStackTrace();}return coordinate;}/*** Author AlphaJunS* Date 18:26 2020/3/7* Description 获取关键字所在PDF坐标* param pdfReader* param keyWords* return float[]*/private static float[] getKeyWords(PdfReader pdfReader, String keyWords) {float[] coordinate null;int page 0;try{int pageNum pdfReader.getNumberOfPages();PdfReaderContentParser pdfReaderContentParser new PdfReaderContentParser(pdfReader);CustomRenderListener renderListener new CustomRenderListener();renderListener.setKeyWord(keyWords);for (page 1; page pageNum; page) {renderListener.setPage(page);pdfReaderContentParser.processContent(page, renderListener);coordinate renderListener.getPcoordinate();if (coordinate ! null) break;}} catch (IOException e) {e.printStackTrace();}return coordinate;}public static void main(String[] args) {float[] keyWordsByPath getKeyWordsByPath(D:\\SoftPackage\\InterDowloads\\优选东莞汽车服务有限公司-登记审核表.pdf, 东莞市);for(float f : keyWordsByPath){System.out.println(f);}
// 238.35
// 141.6
// 1.0}
}三、总结
高效、便携、易上手