C# -- ITextSharp生成带水印的PDF

   上周按需求需要在系统上实现PDF带水印文档的导出,网上搜了一下发现开源的组件还挺多的,用的比较多的是ITextsharp,Demo也相对较多,就它了!

   (一)首先下载ITextSharp.dll,可在官网上下载:http://sourceforge.net/projects/itextsharp/,本人用了itextsharp-dll-core文件夹下的dll。

   (二)网上有很多类似的Demo和ITextSharp各属性的详细讲解,就不做重复累赘了,可自行百度参考。

   (三)使用过程:在需要的地方调用CreatePDF.Instance.GeneratePDF()即可,详细代码如下:

  1 //要用到的命名空间
  2     using System.IO;
  3     using iTextSharp.text;
  4     using iTextSharp.text.pdf;
  5     using System.Text;
  6     using System.Data;
  7     public class CreatePDF
  8     {
  9         private static CreatePDF instance;
 10         public static CreatePDF GetInstance()
 11         {
 12             if (instance == null)
 13             {
 14                 instance = new CreatePDF();
 15             }
 16             return instance;
 17         }
 18 
 19         private static Document doc;
 20         private static BaseFont bf = BaseFont.CreateFont(@"C://Windows/Fonts/simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
 21         //四种字体
 22         private static Font fontBig = new Font(bf, 20, Font.BOLD);
 23         private static Font fontMiddle = new Font(bf, 15, Font.BOLD);
 24         private static Font fontSmall = new Font(bf, 13, Font.BOLD);
 25         private static Font fontSmallNoBold = new Font(bf, 13);
 26         private static float IndentationLeft = 50;//距左边距
 27         //如果要传参数进来,可自定义
 28         public void GeneratePDF()
 29         {
 30             doc = new Document(PageSize.A4);
 31             try
 32             {
 33                 //MemoryStream ms2 = new MemoryStream();
 34                 string fileName = string.Format("数据_{0}.pdf", DateTime.Now.ToString("yyyyMMddHHmmss"));
 35                 string filePath = string.Format("{0}/Resource/{1}", AppDomain.CurrentDomain.BaseDirectory, fileName);
 36                 FileStream fs = new FileStream(filePath, FileMode.Create);//创建临时文件,到时生成好后删除
 37                 PdfWriter writer = PdfWriter.GetInstance(doc, fs);
 38                 writer.CloseStream = false;//把doc内容写入流中
 39                 doc.Open();
 40 
 41                 //核心操作
 42                 CreateLine();//生成一条下横线
 43                 CreateEmptyRow(1);//生成一行空行
 44                 AddHeaderTitleContent("表10 已安装工程量明细表");//添加表头
 45                 CreateEmptyRow(1);//生成一行空行
 46                 AddPartnerContent("工程名称", "建设名称", "施工名称", "监理名称");//添加合作单位
 47                 AddPageNumberContent();//添加页码
 48                 CreateEmptyRow(1);//生成一行空行
 49 
 50                 #region 生成表格数据
 51                 PdfPTable table = new PdfPTable(6);//6列的table
 52                 //添加表格列头               
 53                 table.SetTotalWidth(new float[] { 50, 200, 60, 60, 100, 100 });
 54                 table.AddCell(GetPdfCell("序号", fontSmallNoBold, Element.ALIGN_CENTER));
 55                 table.AddCell(GetPdfCell("工程量名称", fontSmallNoBold, Element.ALIGN_CENTER));
 56                 table.AddCell(GetPdfCell("单位", fontSmallNoBold, Element.ALIGN_CENTER));
 57                 table.AddCell(GetPdfCell("数量", fontSmallNoBold, Element.ALIGN_CENTER));
 58                 table.AddCell(GetPdfCell("安装地点、路段", fontSmallNoBold, Element.ALIGN_CENTER));
 59                 table.AddCell(GetPdfCell("备注", fontSmallNoBold, Element.ALIGN_CENTER));
 60 
 61                 int emptyRow = 20;//如果table的行数小于20行,那么剩余部分显示空白行
 62                 #region 构造数据源
 63                 DataTable tableSource = new DataTable();
 64                 tableSource.Columns.Add(new DataColumn("aa"));
 65                 tableSource.Columns.Add(new DataColumn("bb"));
 66                 tableSource.Columns.Add(new DataColumn("cc"));
 67                 tableSource.Columns.Add(new DataColumn("dd"));
 68                 tableSource.Columns.Add(new DataColumn("ee"));
 69                 for (int i = 0; i < 15; i++)
 70                 {
 71                     DataRow row = tableSource.NewRow();
 72                     row["aa"] = "aa";
 73                     row["bb"] = "bb";
 74                     row["cc"] = "cc";
 75                     row["dd"] = "dd";
 76                     row["ee"] = "ee";
 77                     tableSource.Rows.Add(row);
 78                 }
 79                 #endregion
 80                 if (tableSource.Rows.Count > 0)
 81                 {
 82                     emptyRow = emptyRow - tableSource.Rows.Count;//如果为负数,说明不需要生成空白行
 83                     for (int i = 0; i < tableSource.Rows.Count; i++)
 84                     {
 85                         DataRow row = tableSource.Rows[i];
 86                         table.AddCell(GetPdfCell((i + 1).ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 87                         table.AddCell(GetPdfCell(row["aa"].ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 88                         table.AddCell(GetPdfCell(row["bb"].ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 89                         table.AddCell(GetPdfCell(row["cc"].ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 90                         table.AddCell(GetPdfCell(row["dd"].ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 91                         table.AddCell(GetPdfCell(row["ee"].ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 92                     }
 93                 }
 94                 if (emptyRow > 0)//说明数据源不足20行
 95                 {
 96                     for (int i = 0; i < emptyRow; i++)
 97                     {
 98                         table.AddCell(GetPdfCell(((20 - emptyRow) + i + 1).ToString(), fontSmallNoBold, Element.ALIGN_CENTER));
 99                         table.AddCell(GetPdfCell("", fontSmallNoBold, Element.ALIGN_CENTER));
100                         table.AddCell(GetPdfCell("", fontSmallNoBold, Element.ALIGN_CENTER));
101                         table.AddCell(GetPdfCell("", fontSmallNoBold, Element.ALIGN_CENTER));
102                         table.AddCell(GetPdfCell("", fontSmallNoBold, Element.ALIGN_CENTER));
103                         table.AddCell(GetPdfCell("", fontSmallNoBold, Element.ALIGN_CENTER));
104                     }
105                 }
106                 doc.Add(table); 
107                 #endregion
108 
109                 #region 添加水印
110                 string waterMarkName = "经度:无  纬度:无  地址:无  验收负责人:无";
111                 string waterMarkAddr = "广州市天河区";
112                 if (!string.IsNullOrEmpty(waterMarkAddr))
113                 {
114                     waterMarkName = string.Format("经度:{0}  纬度:{1}  地址:{2}  验收负责人:{3}", "113.211", "23.211", waterMarkAddr, "张三");
115                 } 
116                 #endregion
117                 
118                 doc.Close();
119                 MemoryStream ms = new MemoryStream();
120                 if (fs != null)
121                 {
122                     byte[] bytes = new byte[fs.Length];//定义一个长度为fs长度的字节数组
123                     fs.Read(bytes, 0, (int)fs.Length);//把fs的内容读到字节数组中
124                     ms.Write(bytes, 0, bytes.Length);//把字节内容读到流中
125                     fs.Flush();
126                     fs.Close();
127                 }
128                 MemoryStream waterMS = SetWaterMark(ms, filePath, waterMarkName);//先生成水印,再删除临时文件
129                 if (File.Exists(filePath))//判断临时文件是否存在,如果存在则删除
130                 {
131                     File.Delete(filePath);
132                     GC.Collect();//回收垃圾
133                 }
134                 SendFile(fileName, waterMS);//把PDF文件发送回浏览器
135             }
136             catch (DocumentException ex)
137             {
138                 throw new Exception(ex.Message);
139             }
140         }
141         #region 生成一条横线
142         private static void CreateLine()
143         {
144             PdfPTable table = new PdfPTable(1);//一个单元格的
145             table.TotalWidth = 500;
146             PdfPCell cell = new PdfPCell();
147             cell.BorderWidthBottom = 0.5f;
148             table.AddCell(cell);
149             doc.Add(table);
150         }
151         #endregion
152 
153         #region 生成N行空白行
154         private static void CreateEmptyRow(int emptyRowNum)
155         {
156             for (int i = 0; i < emptyRowNum; i++)
157             {
158                 doc.Add(new Paragraph(" "));
159             }
160         }
161         #endregion
162 
163         #region 生成标题
164         private static void AddHeaderTitleContent(string content)
165         {
166             Paragraph p = new Paragraph(content, fontMiddle);
167             p.IndentationLeft = IndentationLeft;//距离左边距
168             doc.Add(p);
169         }
170         #endregion
171 
172         #region 生成合作单位
173         private static void AddPartnerContent(string stationName, string constructUnit, string buildUnit, string supervisionUnit)
174         {
175             fontMiddle.SetStyle(Font.UNDERLINE);//文字下划线
176             IndentationLeft = IndentationLeft + 10;
177 
178             Paragraph content = new Paragraph();
179             content.IndentationLeft = IndentationLeft;
180             Chunk chunkName = new Chunk("单项或单位工程名称:", fontSmallNoBold);
181             Chunk chunkText = new Chunk(GetEmptyString(25, stationName), fontMiddle);
182             content.Add(0, chunkName);
183             content.Add(1, chunkText);
184             content.Alignment = 3;
185             doc.Add(content);
186 
187             content = new Paragraph();
188             content.IndentationLeft = IndentationLeft;
189             chunkName = new Chunk("建设单位名称:", fontSmallNoBold);
190             chunkText = new Chunk(GetEmptyString(30, constructUnit), fontMiddle);
191             content.Add(0, chunkName);
192             content.Add(1, chunkText);
193             content.Alignment = 3;
194             doc.Add(content);
195 
196             content = new Paragraph();
197             content.IndentationLeft = IndentationLeft;
198             chunkName = new Chunk("施工单位名称:", fontSmallNoBold);
199             chunkText = new Chunk(GetEmptyString(30, buildUnit), fontMiddle);
200             content.Add(0, chunkName);
201             content.Add(1, chunkText);
202             content.Alignment = 3;
203             doc.Add(content);
204 
205             content = new Paragraph();
206             content.IndentationLeft = IndentationLeft;
207             chunkName = new Chunk("监理单位名称:", fontSmallNoBold);
208             chunkText = new Chunk(GetEmptyString(30, supervisionUnit), fontMiddle);
209             content.Add(0, chunkName);
210             content.Add(1, chunkText);
211             content.Alignment = 3;
212             doc.Add(content);
213         }
214         //居中显示内容
215         private static string GetEmptyString(int maxlength, string text)
216         {
217             int padding = (maxlength - text.Length * 2) / 2;
218             string empty = string.Empty;
219             for (int i = 0; i < padding; i++)
220             {
221                 empty += " ";
222             }
223             return string.Format("{0}{1}{0}", empty, text);
224         }
225         #endregion
226 
227         #region 生成页码
228         private static void AddPageNumberContent()
229         {
230             var content = new Paragraph("共   页  第   页", fontSmall);
231             content.IndentationRight = IndentationLeft + 20;
232             content.Alignment = 2;    //居左
233             doc.Add(content);
234         }
235         #endregion
236 
237         #region 生成单元格
238         private static PdfPCell GetPdfCell(string content, Font font, int horizontalAlignment)
239         {
240             PdfPCell cell = new PdfPCell(new Paragraph(content, font));
241             cell.HorizontalAlignment = horizontalAlignment;//水平位置
242             cell.VerticalAlignment = Element.ALIGN_CENTER;//垂直居中
243             cell.MinimumHeight = 20;//单元格的最小高度
244             return cell;
245         }
246         #endregion
247 
248         #region 生成水印
249         private static MemoryStream SetWaterMark(MemoryStream ms, string filePath, string waterMarkName, string waterMarkAddr = null)
250         {
251             MemoryStream msWater = new MemoryStream();
252             PdfReader pdfReader = null;
253             PdfStamper pdfStamper = null;
254             try
255             {
256                 pdfReader = new PdfReader(filePath);
257                 pdfStamper = new PdfStamper(pdfReader, msWater);
258 
259                 int total = pdfReader.NumberOfPages + 1;//获取PDF的总页数
260                 iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);//获取第一页
261                 float width = psize.Width;//PDF页面的宽度,用于计算水印倾斜
262                 float height = psize.Height;
263                 PdfContentByte waterContent;
264                 BaseFont basefont = BaseFont.CreateFont(@"C:WINDOWSFontsSIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
265                 PdfGState gs = new PdfGState();
266                 for (int i = 1; i < total; i++)
267                 {
268                     waterContent = pdfStamper.GetOverContent(i);//在内容上方加水印
269                     //透明度
270                     waterContent.SetGState(gs);
271                     //开始写入文本
272                     waterContent.BeginText();
273                     waterContent.SetColorFill(BaseColor.RED);
274                     waterContent.SetFontAndSize(basefont, 18);
275                     waterContent.SetTextMatrix(0, 0);
276                     if (waterMarkAddr == null || waterMarkAddr == "")
277                     {
278                         waterContent.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2, height / 2, 55);
279                     }
280                     else
281                     {
282                         waterContent.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2, height / 2 + 100, 55);
283                         waterContent.ShowTextAligned(Element.ALIGN_CENTER, waterMarkAddr, width / 2, height / 2 - 100, 55);
284                     }
285                     waterContent.EndText();
286                 }
287             }
288             catch (Exception)
289             {
290                 return ms;
291             }
292             finally
293             {
294                 if (pdfStamper != null)
295                     pdfStamper.Close();
296 
297                 if (pdfReader != null)
298                     pdfReader.Close();
299             }
300             return msWater;
301         }
302         #endregion
303 
304         //-----------------------发送PDF文件回浏览器端----------------------
305         public static void SendFile(string fileName, MemoryStream ms, Encoding encoding = null)
306         {
307             fileName = (fileName + "").Replace(" ", "");
308             encoding = encoding ?? Encoding.UTF8;
309             if (ms != null && !string.IsNullOrEmpty(fileName))
310             {
311                 System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
312                 response.Clear();
313                 response.Charset = encoding.BodyName;// "utf-8";
314                 if (!HttpContext.Current.Request.UserAgent.Contains("Firefox") && !HttpContext.Current.Request.UserAgent.Contains("Chrome"))
315                 {
316                     fileName = HttpUtility.UrlEncode(fileName, encoding);
317                 }
318                 response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
319                 //为了解决打开,导出NPOI生成的xlsx文件时,提示发现不可读取内容。
320                 if (!(fileName + "").ToLower().EndsWith(".xlsx"))
321                 {
322                     response.AddHeader("Content-Type", "application/octet-stream");
323                     response.BinaryWrite(ms.GetBuffer());
324                 }
325                 else
326                 {
327                     response.BinaryWrite(ms.ToArray());
328                 }
329                 ms.Close();
330                 ms = null;
331                 response.Flush();
332                 response.End();
333             }
334         }
335     }
View Code

   (四)总结:

     从代码上,不难看出,普遍用到的标签大多为Document、Paragraph、Table、Cell、Chunck、Font、Element,通过这些标签大概能组合出自己想要的效果,有点类似Html思想。

      a.通过Paragraph、chunck即可显示行元素,若要设置间距或居中等效果,需要熟悉对属性的使用,如设置居中需要Element.ALIGN_CENTER

      b.table操作cell,cell内要添加Paragraph来显示内容,如果需要跨行跨列效果,则可通过cell.Colspan或cell.Rowspan来设置,

      c.实现上不难,如果要达到自己的效果,得多熟悉元素属性的使用和多思考多实践    

     

原文地址:https://www.cnblogs.com/jean69/p/6197740.html