[WEB API]使用ITextSharp將PDF印上浮水印,提供下載

[WEB API]使用ITextSharp將PDF印上浮水印,提供下載

前言

其實這種需求在銀行業還蠻常見的,因為個資問題,可能會怕人把文件隨便外流出去,所以當你下載某個檔案的時候,就印上你的姓名甚至部門,一旦在市面上看到文件,就可以追蹤法律職責的問題,但其實這一套就是為了製作pdf而生的,所以你可以完全用這個搭配上你能抓到的所有資料或者圖片,然後用程式碼自動產生一份pdf出來,不過在本篇文章只會介紹一下如何印上logo而已,其餘進階議題就留給讀者自行研究了,ITextSharp的說明文件的網頁實在不是那麼好找,所以在此也附上連結,如果需要進一步去使用的話,就好好看著官網學習吧(http://developers.itextpdf.com/content/itext-7-jump-start-tutorial-net/itext-7-jump-start-tutorial-net-version)

導覽

  1. 安裝ITextSharp
  2. 開始動手實作
  3. 印上文字
  4. 結論

安裝ITextSharp

開啟nuget下載ITextSharp,你可以只選擇pdfa,不過為了以防我要使用到某種情境卻沒有支援,所以我還是建議直接下載最完整的吧

開始動手實做

先準備一份pdf還有logo吧

接下來就可以開始寫C#的程式碼了,我會把比較不太好懂的屬性寫上註解,這邊為了文章排版方便,所以全部放在一起,方便在文章好閱讀,但是在ide上請自行好好重構,印上圖片最主要是依賴在

 public HttpResponseMessage Get()
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            using (MemoryStream myMemoryStream = new MemoryStream())
            {
                var path = HttpContext.Current.Server.MapPath("/File/react-sample.pdf");

                using (PdfReader pdfReader = new PdfReader(path))
                {
                    using (PdfStamper stamp = new PdfStamper(pdfReader, myMemoryStream))
                    {
                        BaseFont bfChinese = BaseFont.CreateFont(@"C:\WINDOWS\Fonts\kaiu.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                        PdfGState gstate = new PdfGState()
                        {
                            FillOpacity = 0.6f,
                            StrokeOpacity = 0.6f
                        };

                        for (int page = 1; page <= pdfReader.NumberOfPages; page++)
                        {
                            PdfContentByte pdfPageContents = stamp.GetOverContent(page);
                            pdfPageContents.SetGState(gstate); //塞入我們設定的透明度
                            string imageUrl = HttpContext.Current.Server.MapPath("/File/fb.png");
                            iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(imageUrl);
                            img.ScalePercent(35f);  //縮放比例
                            img.RotationDegrees = 45; //旋轉角度
                            img.SetAbsolutePosition(100,100); //設定圖片每頁的絕對位置
                            PdfContentByte waterMark = stamp.GetOverContent(page);
                            waterMark.AddImage(img); //把圖片印上去 
                        }
                    }
                }
               
                response.Content = new ByteArrayContent(myMemoryStream.ToArray());
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                response.Content.Headers.ContentDisposition.FileName = HttpUtility.UrlPathEncode("react-example.pdf");
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                response.StatusCode = HttpStatusCode.OK;
            }

            return response;
        }

檔案下載之後可以看到已印上fb的logo了

印上文字

上面已經印上logo了,如果我們想要印上姓名怎麼做呢,接著請再參考程式碼做法

        public HttpResponseMessage Get()
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            using (MemoryStream myMemoryStream = new MemoryStream())
            {
                var path = HttpContext.Current.Server.MapPath("/File/react-sample.pdf");

                using (PdfReader pdfReader = new PdfReader(path))
                {
                    using (PdfStamper stamp = new PdfStamper(pdfReader, myMemoryStream))
                    {
                        BaseFont bfChinese = BaseFont.CreateFont(@"C:\WINDOWS\Fonts\kaiu.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                        PdfGState gstate = new PdfGState()
                        {
                            FillOpacity = 0.6f,
                            StrokeOpacity = 0.6f
                        };

                        for (int page = 1; page <= pdfReader.NumberOfPages; page++)
                        {
                            PdfContentByte pdfPageContents = stamp.GetOverContent(page);
                            pdfPageContents.SetGState(gstate); 
                            string imageUrl = HttpContext.Current.Server.MapPath("/File/fb.png");
                            iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(imageUrl);
                            img.ScalePercent(35f); 
                            img.RotationDegrees = 45; 
                            img.SetAbsolutePosition(100,100); 
                            PdfContentByte waterMark = stamp.GetOverContent(page);
                            waterMark.AddImage(img);

                            // 加入所需文字和一些設定
                            float fontSize = 36;
                            float adjustTxtLineHeight = fontSize - 4;
                            float txtMarginTop = 5;
                            pdfPageContents.BeginText();
                            pdfPageContents.SetFontAndSize(bfChinese, fontSize);
                            pdfPageContents.SetRGBColorFill(210, 210, 210);
                            pdfPageContents.SetGState(gstate);

                            pdfPageContents.ShowTextAligned(PdfContentByte.ALIGN_LEFT, "react好潮哦,但是我更愛vue", 200, 200, 45);
                        }
                    }
                }
               
                response.Content = new ByteArrayContent(myMemoryStream.ToArray());
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                response.Content.Headers.ContentDisposition.FileName = HttpUtility.UrlPathEncode("react-example.pdf");
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                response.StatusCode = HttpStatusCode.OK;
            }

            return response;
        }

結果

 

結論

其實ITextSharp能做的事情非常多,而且做一樣的事情又有很多方式可以完成,其實本身也蠻複雜的,有興趣的讀者就再自行研究了,筆者在此就不獻醜了。