C# 通过iTextSharp实现关键字签字盖章(通过在内容中插入盖章图片的形式)
此功能通过 iTextSharp 读取PDF文档信息,并循环查找每一页PDF文件,在整个PDF中只要是符合条件的地方都会盖章,如只需要在最后一页盖章,请将方法中For循环去掉,并将
PdfContentByte contentByte = pdfStamper.GetUnderContent(i);
parser.ProcessContent<PdfLocation>(i, location);
改为
// 获得文档页数 int pdfPageSize = pdfReader.NumberOfPages; //文档最后一页,如需要第一页则直接将pdfPageSize改为1 PdfContentByte contentByte = pdfStamper.GetUnderContent(pdfPageSize); //读取文档最后一页内容 parser.ProcessContent<PdfLocation>(pdfPageSize, location);
这几句改掉之后即可精确到第几页盖章
以下为具体代码实现:
1、具体盖章实现,引用 iTextSharp.text.pdf
/// <summary> /// pdf签字签章,以图片形式 /// </summary> public class PDFSealHelper { /// <summary> /// 图片最大宽度 /// </summary> private static float ReSizeMaxWidth = 50; /// <summary> /// 图片最大高度 /// </summary> private static float ReSizeMaxHeight = 50; /// <summary> /// 签字盖章(文件流和Base64格式图片) /// </summary> /// <param name="bytePdf">需要签字盖章byte数组的pdf文件</param> /// <param name="outPdfPath">签字盖章后输出pdf路径</param> /// <param name="SignImgBase64">Base64格式图片</param> /// <param name="SignKeyWord">关键字</param> public static void SignBase64Img(byte[] bytePdf, string outPdfPath, string SignImgBase64, string SignKeyWord) { System.IO.Stream outputPdfStream = new System.IO.FileStream(outPdfPath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None); // 创建一个PdfReader对象 PdfReader pdfReader = new PdfReader(bytePdf); PdfStamper pdfStamper = new PdfStamper(pdfReader, outputPdfStream); { // 获得文档页数 int pdfPageSize = pdfReader.NumberOfPages; for (int i = 1; i <= pdfPageSize; i++) { //获取当前页 PdfContentByte contentByte = pdfStamper.GetUnderContent(i); PdfLocation location = new PdfLocation(); iTextSharp.text.pdf.parser.PdfReaderContentParser parser = new iTextSharp.text.pdf.parser.PdfReaderContentParser(pdfReader); parser.ProcessContent<PdfLocation>(i, location); //查找当前页的关键字 location.SearchKeywords(SignKeyWord); if (location.TextLocationInfo.Count > 0) { //坐标是从左下角往上,左下角为(0,0)零点 XTextInfo o = location.TextLocationInfo[0]; //获取关键字左上角开始坐标 var ltLocation = o.TopLeft.ToString().Split(',');//272.15,766.46,1 var leftX = float.Parse(ltLocation[0]); var topY = float.Parse(ltLocation[1]); //获取关键字右下角结束坐标 var rbLocation = o.BottomRight.ToString().Split(',');//305.15,755.46,1 var rightX = float.Parse(rbLocation[0]); var bottomY = float.Parse(rbLocation[1]); //计算得到关键字的中心点 float x = (rightX - leftX) / 2 + leftX; float y = (topY - bottomY) / 2 + bottomY; var imageByByte = ConvertBase64ToImage(SignImgBase64); //创建一个图片对象 iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageByByte, System.Drawing.Imaging.ImageFormat.Jpeg); //设置图片的指定大小 float expectWidth = image.Width; float expectHeight = image.Height; if (image.Width > image.Height && image.Width > ReSizeMaxWidth) { expectWidth = ReSizeMaxWidth; expectHeight = expectWidth * image.Height / image.Width; } else if (image.Height > image.Width && image.Height > ReSizeMaxHeight) { expectHeight = ReSizeMaxHeight; expectWidth = expectHeight * image.Width / image.Height; } //设置图片的指定大小 image.ScalePercent(40); //image.ScaleToFit(expectWidth, expectHeight); //盖章位置于关键字右下方 image.SetAbsolutePosition(x + (expectWidth / 2), y + (expectHeight / 2) - expectHeight); contentByte.AddImage(image); } } pdfStamper.Close(); pdfReader.Close(); System.Diagnostics.Process.Start(outPdfPath); } } /// <summary> /// 签字盖章(文件路径) /// </summary> /// <param name="pdfPath">要签字盖章的pdf文件路径</param> /// <param name="outPdfPath">签字盖章后输出pdf路径</param> /// <param name="SignImgPath">签字的图片路径</param> /// <param name="SignKeyWord">关键字</param> public static void SignFile(string pdfPath, string outPdfPath, string SignImgPath, string SignKeyWord) { //创建盖章后生成pdf System.IO.Stream outputPdfStream = new System.IO.FileStream(outPdfPath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None); // 创建一个PdfReader对象 PdfReader pdfReader = new PdfReader(pdfPath); PdfStamper pdfStamper = new PdfStamper(pdfReader, outputPdfStream); // 获得文档页数 int pdfPageSize = pdfReader.NumberOfPages; //循环每一页 for (int i = 1; i <= pdfPageSize; i++) { //获取当前页 //GetUnderContent 加在内容下层 //GetOverContent 加在内容上层 PdfContentByte contentByte = pdfStamper.GetUnderContent(i); PdfLocation location = new PdfLocation(); iTextSharp.text.pdf.parser.PdfReaderContentParser parser = new iTextSharp.text.pdf.parser.PdfReaderContentParser(pdfReader); parser.ProcessContent<PdfLocation>(i, location); //查找当前页的关键字及其坐标 location.SearchKeywords(SignKeyWord); if (location.TextLocationInfo.Count > 0) { XTextInfo o = location.TextLocationInfo[0]; //获取关键字左上角开始坐标 var ltLocation = o.TopLeft.ToString().Split(',');//272.15,766.46,1 var leftX = float.Parse(ltLocation[0]); var topY = float.Parse(ltLocation[1]); //获取关键字右下角结束坐标 var rbLocation = o.BottomRight.ToString().Split(',');//305.15,755.46,1 var rightX = float.Parse(rbLocation[0]); var bottomY = float.Parse(rbLocation[1]); //计算得到关键字的中心点 float x = (rightX - leftX) / 2 + leftX; float y = (topY - bottomY) / 2 + bottomY; //创建一个图片对象 iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(SignImgPath); float expectWidth = image.Width; float expectHeight = image.Height; if (image.Width > image.Height && image.Width > ReSizeMaxWidth) { expectWidth = ReSizeMaxWidth; expectHeight = expectWidth * image.Height / image.Width; } else if (image.Height > image.Width && image.Height > ReSizeMaxHeight) { expectHeight = ReSizeMaxHeight; expectWidth = expectHeight * image.Width / image.Height; } //设置图片的指定大小 image.ScalePercent(40); //image.ScaleToFit(expectWidth, expectHeight); //盖章位置于关键字右下方 image.SetAbsolutePosition(x + (expectWidth / 2), y + (expectHeight / 2) - expectHeight); contentByte.AddImage(image); } } pdfStamper.Close(); pdfReader.Close(); System.Diagnostics.Process.Start(outPdfPath); } /// <summary> /// Base64转图片 /// </summary> /// <param name="base64String"></param> /// <returns></returns> private static System.Drawing.Image ConvertBase64ToImage(string base64String) { byte[] imageBytes = Convert.FromBase64String(base64String); System.Drawing.Bitmap bitmap = null; MemoryStream stream = null; stream = new MemoryStream(imageBytes); bitmap = new System.Drawing.Bitmap(stream); return bitmap; } }
2、查找pdf关键字坐标类,引用 iTextSharp.text.pdf.parser
public class PdfLocation : LocationTextExtractionStrategy { /// <summary> /// 文档文本及坐标 /// </summary> public List<XTextChunk> LocationResult = new List<XTextChunk>(); /// <summary> /// 关键字及其坐标 /// </summary> public List<XTextInfo> TextLocationInfo = new List<XTextInfo>(); /// <summary> /// 重写读取文档文本方法,第一步就是执行此方法,不可删除, /// 删除后LocationResult数据为空,影响关键字坐标查找方法执行 /// </summary> /// <param name="renderInfo">文本渲染信息</param> public override void RenderText(TextRenderInfo renderInfo) { LineSegment segment = renderInfo.GetBaseline(); XTextChunk location = new XTextChunk(renderInfo.GetText(), segment.GetStartPoint(), segment.GetEndPoint(), renderInfo.GetSingleSpaceWidth(), renderInfo.GetAscentLine(), renderInfo.GetDescentLine()); LocationResult.Add(location); } /// <summary> /// 关键字坐标查找 /// </summary> /// <param name="sKeyword">关键字</param> public void SearchKeywords(string sKeyword) { var keyWordLen = sKeyword.Length; var keyWordList = sKeyword.ToList(); LocationResult.Sort(); TextLocationInfo.Clear(); XTextInfo lastXTextInfo = new XTextInfo(); if (LocationResult != null && LocationResult.Any()) { for (int i = 0; i < LocationResult.Count; i++) { //当关键字的第一个字匹配上后循环匹配后面的几个关键字 if (LocationResult[i].Text == keyWordList[0].ToString()) { if (keyWordLen > 1) { for (int j = 0; j < keyWordList.Count; j++) { //往后几个字符都符合关键字 if (LocationResult[i + j].Text == keyWordList[j].ToString()) { lastXTextInfo.appendText(LocationResult[i + j]); } } } else { lastXTextInfo.appendText(LocationResult[i]); } if (lastXTextInfo.Text.Contains(sKeyword)) { TextLocationInfo.Add(lastXTextInfo); break; } } } } } } /// <summary> /// 文本块 /// </summary> public class XTextChunk : IComparable, ICloneable { #region 字段 /// <summary> /// 上升线段 /// </summary> public LineSegment AscentLine { get; set; } /// <summary> /// 下降线段 /// </summary> public LineSegment DecentLine { get; set; } /// <summary> /// 方向 /// </summary> public Vector OrientationVector { get; set; } /// <summary> /// 文本 /// </summary> public string Text { get; set; } /// <summary> /// 字符宽度 /// </summary> public float CharSpaceWidth { get; set; } /// <summary> /// 平行距离开始 /// </summary> public float DistParallelStart { get; set; } /// <summary> /// 平行距离结束 /// </summary> public float DistParallelEnd { get; set; } /// <summary> /// 垂直距离 /// </summary> public int DistPerpendicular { get; set; } /// <summary> /// 方向幅值(坐标角度) /// </summary> public int OrientationMagnitude { get; set; } /// <summary> /// 开始坐标 /// </summary> public Vector StartLocation { get; set; } /// <summary> /// 结束坐标 /// </summary> public Vector EndLocation { get; set; } #endregion /// <summary> /// 文本块、它的方向以及相对于方向向量的位置 /// </summary> /// <param name="txt"></param> /// <param name="startLoc"></param> /// <param name="endLoc"></param> /// <param name="charSpaceWidth"></param> public XTextChunk(string txt, Vector startLoc, Vector endLoc, float charSpaceWidth, LineSegment ascentLine, LineSegment decentLine) { Text = txt; StartLocation = startLoc; EndLocation = endLoc; CharSpaceWidth = charSpaceWidth; AscentLine = ascentLine; DecentLine = decentLine; OrientationVector = EndLocation.Subtract(StartLocation).Normalize(); OrientationMagnitude = (int)(Math.Atan2(OrientationVector[Vector.I2], OrientationVector[Vector.I1]) * 1000); Vector origin = new Vector(0, 0, 1); DistPerpendicular = (int)(StartLocation.Subtract(origin)).Cross(OrientationVector)[Vector.I3]; DistParallelStart = OrientationVector.Dot(StartLocation); DistParallelEnd = OrientationVector.Dot(EndLocation); } /// <summary> /// 创建作为当前实例副本的新对象。 /// </summary> /// <returns></returns> public object Clone() { XTextChunk copy = new XTextChunk(Text, StartLocation, EndLocation, CharSpaceWidth, AscentLine, DecentLine); return copy; } /// <summary> /// 根据方向、垂直距离和平行距离进行比较 /// </summary> /// <param name="obj"></param> /// <returns></returns> public int CompareTo(object obj) { if (obj == null) {throw new Exception ("obj参数为空");} XTextChunk rhs = obj as XTextChunk; if (rhs != null) { if (this == rhs) { return 0; } int rslt = OrientationMagnitude - rhs.OrientationMagnitude; if (rslt != 0) { return rslt; } rslt = DistPerpendicular - rhs.DistPerpendicular; if (rslt != 0) { return rslt; } //注意:检查浮点数是否相等是不安全的,如果两个块 //真的在彼此之上,哪一个排在第一还是第二并不重要 //所以我们任意选择了这种方式。 rslt = DistParallelStart < rhs.DistParallelStart ? -1 : 1; return rslt; } else { throw new Exception ("XTextChunk为空"); } } } /// <summary> /// 符合条件的文本信息 /// </summary> public class XTextInfo { #region 字段 /// <summary> /// 左上角开始坐标 /// </summary> public Vector TopLeft { get; set; } /// <summary> /// 右下角结束坐标 /// </summary> public Vector BottomRight { get; set; } /// <summary> /// 关键字 /// </summary> public string Text { get; set; } #endregion #region 构造方法 /// <summary> /// 构造方法 /// </summary> /// <param name="initialXTextChunk"></param> public XTextInfo(XTextChunk initialXTextChunk) { //上升线=AscentLine TopLeft = initialXTextChunk.AscentLine.GetStartPoint(); BottomRight = initialXTextChunk.DecentLine.GetEndPoint(); Text = initialXTextChunk.Text; } /// <summary> /// 构造方法 /// </summary> public XTextInfo() { } #endregion /// <summary> /// 添加文本 /// </summary> /// <param name="additionalXTextChunk"></param> public void appendText(XTextChunk additionalXTextChunk) { //DecentLine=下降线 BottomRight = additionalXTextChunk.DecentLine.GetEndPoint(); TopLeft = additionalXTextChunk.AscentLine.GetStartPoint(); Text += additionalXTextChunk.Text; } }
本文来自博客园,作者:流纹,转载请注明原文链接:https://www.cnblogs.com/lwk9527/p/17374155.html