开发笔记:PDF生成文字和图片水印

背景

团队手里在做的一个项目,其中一个小功能是用户需要上传PDF文件到文件服务器上,都是一些合同或者技术评估文档,鉴于知识版权和防伪的目的,需要在上传的PDF文件打上水印,

这时候我们需要提供能力给客户,让他们可以对自己上传的文档,配置文字或者图片水印。

实现

于是我们参考了网上的一些资料,首选Spire.Pdf 和 iTextSharp,资料很多,是专业的PDF操作组件。

Spire.Pdf

Spire Nuget安装

直接安装最新的版本就可以了

  

Spire 代码段

这是生成图片水印,注释很清晰了。

 1  #region Spire.Pdf 组件
 2             
 3             //创建PdfDocument对象
 4             PdfDocument pdf = new PdfDocument();
 5             //加载现有PDF文档
 6             pdf.LoadFromFile(@"E:\WaterMark\ATAM.pdf");
 7             //加载图片到System.Drawing.Image对象
 8              System.Drawing.Image image = System.Drawing.Image.FromFile(@"E:\WaterMark\logo.png");
 9             //遍历文档每一页(可以指定只是轮询某一个页面)
10             foreach (PdfPageBase page in pdf.Pages)
11             {
12                 //设置背景图
13                 page.BackgroundImage = image;
14                 //设置背景图的位置及大小(这边根据我们实际的图片大小进行同比缩小)
15                 page.BackgroundRegion = new RectangleF((page.ActualSize.Width - 500) / 2, 
16                     (page.ActualSize.Height - 500)/2, 500, 250);
17                 //设置背景透明度
18                 page.BackgroudOpacity = 0.5f;
19             }
20             //保存并关闭文档(不关闭貌似打开的时候会有异常)
21             pdf.SaveToFile(@"E:\WaterMark\ATAM_WaterMark.pdf");
22             pdf.Close();
23             
24             #endregion

Spire 实现结果

看着还行,起码达到效果了

 

Spire 扩展:文字水印 

 1 //加载PDF文档
 2 PdfDocument pdf = new PdfDocument();
 3 pdf.LoadFromFile(@"E:\WaterMark\ATAM.pdf");
 4 
 5 //获取PDF文档的第一页
 6 PdfPageBase page = pdf.Pages[0];
 7 
 8 //绘制文本,设置文本格式并将其添加到页面
 9 PdfTilingBrush brush = new PdfTilingBrush(new SizeF(page.Canvas.ClientSize.Width / 2, page.Canvas.ClientSize.Height / 3));
10 brush.Graphics.SetTransparency(0.3f);
11 brush.Graphics.Save();
12 brush.Graphics.TranslateTransform(brush.Size.Width / 2, brush.Size.Height / 2);
13 brush.Graphics.RotateTransform(-45);
14 PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Arial Unicode MS", 20f), true);
15 brush.Graphics.DrawString("这边定制你的文字水印", font, PdfBrushes.Red, 0, 0, new PdfStringFormat(PdfTextAlignment.Center));
16 brush.Graphics.Restore();
17 brush.Graphics.SetTransparency(1);
18 page.Canvas.DrawRectangle(brush, new RectangleF(new PointF(0, 0), page.Canvas.ClientSize));
19 
20 //保存文档
21 pdf.SaveToFile(@"E:\WaterMark\ATAM_WaterMark.pdf");
22 pdf.Close();

 

iTextSharp

iTextSharp Nuget安装

一样,直接安装最新版本即可

 

iTextSharp 代码段

这是iTextSharp 生成图片水印的方法代码,注释一样很清晰。

 1         /// <summary>
 2         /// 打水印功能
 3         /// </summary>
 4         /// <param name="infilepath">输入文件地址</param>
 5         /// <param name="outfilepath">输出文件地址</param>
 6         /// <param name="picName">图片文件地址</param>
 7         /// <param name="picHeight">图片高度(可选)</param>
 8         /// <param name="picWidth">图片宽度(可选)</param>
 9         /// <param name="top">图片在PDF中的位置Top(可选)</param>
10         /// <param name="left">图片在PDF中的位置Left(可选)</param>
11         /// <returns></returns>
12         public bool PDFWatermark(string infilepath, string outfilepath, string picName,float picHeight=0,float picWidth=0,float top = 0,float left=0)
13         {
14             PdfReader pdfReader = null;
15             PdfStamper pdfStamper = null;
16             try
17             {
18                 pdfReader = new PdfReader(infilepath);
19                 int numberOfPages = pdfReader.NumberOfPages;
20                 iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
21                 float width = psize.Width;
22                 float height = psize.Height;
23                 pdfStamper = new PdfStamper(pdfReader, new FileStream(outfilepath, FileMode.Create));
24                 PdfContentByte waterMarkContent;
25                 iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(picName);
26                 if (picHeight != 0) image.ScaleAbsoluteHeight(picHeight);
27                 else picHeight = image.Height;
28                 if (picWidth != 0) image.ScaleAbsoluteWidth(picWidth);
29                 else picWidth = image.Width;
30                 image.GrayFill = 20; // 透明度,灰色填充
31                                      // image.Rotation // 旋转
32                                      // image.RotationDegrees // 旋转角度
33                 // 水印的位置 
34                 if (left == 0) left = (width - picWidth) / 2;
35                 if (top == 0) top = (height - picHeight) / 2;
36                 image.SetAbsolutePosition(left,top);
37                 // 每一页加水印,也可以设置某一页加水印 
38                 for (int i = 1; i <= numberOfPages; i++)
39                 {
40                     waterMarkContent = pdfStamper.GetUnderContent(i);//水印在最底层
41                     //这边注意,如果想要水印在最顶层,这边改成 pdfStamper.GetOverContent
42                     waterMarkContent.AddImage(image);
43                 }
44                 return true;
45             }
46             catch (Exception ex)
47             {
48                 ex.Message.Trim();
49                 return false;
50             }
51             finally
52             {
53 
54                 if (pdfStamper != null) pdfStamper.Close();
55                 if (pdfReader != null) pdfReader.Close();
56             }
57         }

 应用

1   #region iTextSharp            
2             string source = @"E:\WaterMark\ATAM.pdf"; //模板路径
3             string output = @"E:\WaterMark\ATAM_WaterMark.pdf"; //导出水印背景后的PDF
4             string watermark = @"E:\WaterMark\logo.png";   // 水印图片
5             bool isSurrcess = PDFWatermark(source, output, watermark,250,500,0,0);            
6  #endregion

 

iTextSharp 实现结果

也不错,这个貌似实现起来更加灵活。

iTextSharp 扩展:文字水印 

 1    /// <summary>
 2         /// 添加文字水印
 3         /// </summary>
 4         /// <param name="filePath">pdf文件地址</param>
 5         /// <param name="text">水印文本</param>
 6         public static void SetWatermark(string filePath, string text)
 7         {
 8             PdfReader pdfReader = null;
 9             PdfStamper pdfStamper = null;
10             string tempPath = Path.GetDirectoryName(filePath) + Path.GetFileNameWithoutExtension(filePath) + "_temp.pdf";
11             try
12             {
13                 pdfReader = new PdfReader(filePath);
14                 pdfStamper = new PdfStamper(pdfReader, new FileStream(tempPath, FileMode.Create));
15                 int total = pdfReader.NumberOfPages + 1;
16                 iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
17                 float width = psize.Width;
18                 float height = psize.Height;
19                 PdfContentByte content;
20                 BaseFont font = BaseFont.CreateFont(@"C:\WINDOWS\Fonts\SIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
21                 PdfGState gs = new PdfGState();
22                 for (int i = 1; i < total; i++)
23                 {
24                     //在内容上方加水印(下方加水印参考上面图片代码做法)
25                     content = pdfStamper.GetOverContent(i);
26                    //透明度
27                     gs.FillOpacity = 0.3f;
28                     content.SetGState(gs);
29                     //写入文本
30                     content.BeginText();
31                     content.SetColorFill(BaseColor.GRAY);
32                     content.SetFontAndSize(font, 30);
33                     content.SetTextMatrix(0, 0);
34                     content.ShowTextAligned(Element.ALIGN_CENTER, text, width - 120, height - 120, -45);
35                     content.EndText();
36                 }
37             }
38             catch (Exception ex)
39             {
40                 throw ex;
41             }
42             finally
43             {
44                 if (pdfStamper != null)pdfStamper.Close();
45                 if (pdfReader != null)pdfReader.Close();
46                 File.Copy(tempPath, filePath, true);
47                 File.Delete(tempPath);//删除临时文件
48             }
49         }

参考资料

Spire.Pdf://www.cnblogs.com/Yesi/p/4913603.html

iTextSharp://www.cnblogs.com/xishuqingchun/p/3838185.html

后记

代码都是片段,没有进一步优化封装,主要是为了验证可行性。两个组件都好用,可以去官网看看文档,有很多功能提供使用。