開發(fā)筆記:PDF生成文字和圖片水印

背景

團(tuán)隊(duì)手里在做的一個(gè)項(xiàng)目梁钾,其中一個(gè)小功能是用戶需要上傳PDF文件到文件服務(wù)器上武契,都是一些合同或者技術(shù)評估文檔栈源,鑒于知識版權(quán)和防偽的目的挡爵,需要在上傳的PDF文件打上水印,

這時(shí)候我們需要提供能力給客戶甚垦,讓他們可以對自己上傳的文檔茶鹃,配置文字或者圖片水印。

實(shí)現(xiàn)

于是我們參考了網(wǎng)上的一些資料艰亮,首選Spire.Pdf 和 iTextSharp闭翩,資料很多,是專業(yè)的PDF操作組件迄埃。

Spire.Pdf

Spire Nuget安裝

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

image

Spire 代碼段

這是生成圖片水印疗韵,注釋很清晰了。

           #region Spire.Pdf 組件
            //創(chuàng)建PdfDocument對象
            PdfDocument pdf = new PdfDocument();
            //加載現(xiàn)有PDF文檔
            pdf.LoadFromFile(@"E:\WaterMark\ATAM.pdf");
            //加載圖片到System.Drawing.Image對象
             System.Drawing.Image image = System.Drawing.Image.FromFile(@"E:\WaterMark\logo.png");
            //遍歷文檔每一頁(可以指定只是輪詢某一個(gè)頁面)
            foreach (PdfPageBase page in pdf.Pages)
            {
                //設(shè)置背景圖
                page.BackgroundImage = image;
                //設(shè)置背景圖的位置及大兄斗恰(這邊根據(jù)我們實(shí)際的圖片大小進(jìn)行同比縮薪锻簟)
                page.BackgroundRegion = new RectangleF((page.ActualSize.Width - 500) / 2,
                    (page.ActualSize.Height - 500)/2, 500, 250);
                //設(shè)置背景透明度
                page.BackgroudOpacity = 0.5f;
            }
            //保存并關(guān)閉文檔(不關(guān)閉貌似打開的時(shí)候會有異常)
            pdf.SaveToFile(@"E:\WaterMark\ATAM_WaterMark.pdf");
            pdf.Close();
            #endregion

Spire 實(shí)現(xiàn)結(jié)果

看著還行流译,起碼達(dá)到效果了

image

Spire 擴(kuò)展:文字水印

//加載PDF文檔
PdfDocument pdf = new PdfDocument();
pdf.LoadFromFile(@"E:\WaterMark\ATAM.pdf");

//獲取PDF文檔的第一頁
PdfPageBase page = pdf.Pages[0];

//繪制文本,設(shè)置文本格式并將其添加到頁面
PdfTilingBrush brush = new PdfTilingBrush(new SizeF(page.Canvas.ClientSize.Width / 2, page.Canvas.ClientSize.Height / 3));
brush.Graphics.SetTransparency(0.3f);
brush.Graphics.Save();
brush.Graphics.TranslateTransform(brush.Size.Width / 2, brush.Size.Height / 2);
brush.Graphics.RotateTransform(-45);
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Arial Unicode MS", 20f), true);
brush.Graphics.DrawString("這邊定制你的文字水印", font, PdfBrushes.Red, 0, 0, new PdfStringFormat(PdfTextAlignment.Center));
brush.Graphics.Restore();
brush.Graphics.SetTransparency(1);
page.Canvas.DrawRectangle(brush, new RectangleF(new PointF(0, 0), page.Canvas.ClientSize));

//保存文檔
pdf.SaveToFile(@"E:\WaterMark\ATAM_WaterMark.pdf");
pdf.Close();

iTextSharp

iTextSharp Nuget安裝

一樣者疤,直接安裝最新版本即可

image

iTextSharp 代碼段

這是iTextSharp 生成圖片水印的方法代碼福澡,注釋一樣很清晰。

        /// <summary>
        /// 打水印功能
        /// </summary>
        /// <param name="infilepath">輸入文件地址</param>
        /// <param name="outfilepath">輸出文件地址</param>
        /// <param name="picName">圖片文件地址</param>
        /// <param name="picHeight">圖片高度(可選)</param>
        /// <param name="picWidth">圖片寬度(可選)</param>
        /// <param name="top">圖片在PDF中的位置Top(可選)</param>
        /// <param name="left">圖片在PDF中的位置Left(可選)</param>
        /// <returns></returns>
        public bool PDFWatermark(string infilepath, string outfilepath, string picName,float picHeight=0,float picWidth=0,float top = 0,float left=0)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            try
            {
                pdfReader = new PdfReader(infilepath);
                int numberOfPages = pdfReader.NumberOfPages;
                iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
                float width = psize.Width;
                float height = psize.Height;
                pdfStamper = new PdfStamper(pdfReader, new FileStream(outfilepath, FileMode.Create));
                PdfContentByte waterMarkContent;
                iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(picName);
                if (picHeight != 0) image.ScaleAbsoluteHeight(picHeight);
                else picHeight = image.Height;
                if (picWidth != 0) image.ScaleAbsoluteWidth(picWidth);
                else picWidth = image.Width;
                image.GrayFill = 20; // 透明度驹马,灰色填充
                                     // image.Rotation // 旋轉(zhuǎn)
                                     // image.RotationDegrees // 旋轉(zhuǎn)角度
                // 水印的位置
                if (left == 0) left = (width - picWidth) / 2;
                if (top == 0) top = (height - picHeight) / 2;
                image.SetAbsolutePosition(left,top);
                // 每一頁加水印,也可以設(shè)置某一頁加水印
                for (int i = 1; i <= numberOfPages; i++)
                {
                    waterMarkContent = pdfStamper.GetUnderContent(i);//水印在最底層
                    //這邊注意革砸,如果想要水印在最頂層,這邊改成 pdfStamper.GetOverContent
                    waterMarkContent.AddImage(image);
                }
                return true;
            }
            catch (Exception ex)
            {
                ex.Message.Trim();
                return false;
            }
            finally
            {

                if (pdfStamper != null) pdfStamper.Close();
                if (pdfReader != null) pdfReader.Close();
            }
        }

應(yīng)用

 #region iTextSharp            
            string source = @"E:\WaterMark\ATAM.pdf"; //模板路徑
            string output = @"E:\WaterMark\ATAM_WaterMark.pdf"; //導(dǎo)出水印背景后的PDF
           string watermark = @"E:\WaterMark\logo.png";   // 水印圖片
           bool isSurrcess = PDFWatermark(source, output, watermark,250,500,0,0);            
 #endregion

iTextSharp 實(shí)現(xiàn)結(jié)果

也不錯(cuò)糯累,這個(gè)貌似實(shí)現(xiàn)起來更加靈活算利。

image

iTextSharp 擴(kuò)展:文字水印

         /// <summary>
        /// 添加文字水印
        /// </summary>
        /// <param name="filePath">pdf文件地址</param>
        /// <param name="text">水印文本</param>
        public static void SetWatermark(string filePath, string text)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            string tempPath = Path.GetDirectoryName(filePath) + Path.GetFileNameWithoutExtension(filePath) + "_temp.pdf";
            try
            {
                pdfReader = new PdfReader(filePath);
                pdfStamper = new PdfStamper(pdfReader, new FileStream(tempPath, FileMode.Create));
                int total = pdfReader.NumberOfPages + 1;
                iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
                float width = psize.Width;
                float height = psize.Height;
                PdfContentByte content;
                BaseFont font = BaseFont.CreateFont(@"C:\WINDOWS\Fonts\SIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                PdfGState gs = new PdfGState();
                for (int i = 1; i < total; i++)
                {
                    //在內(nèi)容上方加水印(下方加水印參考上面圖片代碼做法)
                    content = pdfStamper.GetOverContent(i);
                   //透明度
                    gs.FillOpacity = 0.3f;
                    content.SetGState(gs);
                    //寫入文本
                    content.BeginText();
                    content.SetColorFill(BaseColor.GRAY);
                    content.SetFontAndSize(font, 30);
                    content.SetTextMatrix(0, 0);
                    content.ShowTextAligned(Element.ALIGN_CENTER, text, width - 120, height - 120, -45);
                    content.EndText();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (pdfStamper != null)pdfStamper.Close();
                if (pdfReader != null)pdfReader.Close();
                File.Copy(tempPath, filePath, true);
                File.Delete(tempPath);//刪除臨時(shí)文件
            }
        }

參考資料

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

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

后記

代碼都是片段寇蚊,沒有進(jìn)一步優(yōu)化封裝笔时,主要是為了驗(yàn)證可行性。兩個(gè)組件都好用仗岸,可以去官網(wǎng)看看文檔,有很多功能提供使用借笙。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扒怖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子业稼,更是在濱河造成了極大的恐慌盗痒,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件低散,死亡現(xiàn)場離奇詭異俯邓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)熔号,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門稽鞭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人引镊,你說我怎么就攤上這事朦蕴。” “怎么了弟头?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵吩抓,是天一觀的道長。 經(jīng)常有香客問我赴恨,道長疹娶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任伦连,我火速辦了婚禮雨饺,結(jié)果婚禮上挣饥,老公的妹妹穿的比我還像新娘。我一直安慰自己沛膳,他們只是感情好扔枫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锹安,像睡著了一般短荐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叹哭,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天忍宋,我揣著相機(jī)與錄音,去河邊找鬼风罩。 笑死糠排,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的超升。 我是一名探鬼主播入宦,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼室琢!你這毒婦竟也來了乾闰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盈滴,失蹤者是張志新(化名)和其女友劉穎涯肩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巢钓,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡病苗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了症汹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硫朦。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖烈菌,靈堂內(nèi)的尸體忽然破棺而出阵幸,到底是詐尸還是另有隱情,我是刑警寧澤芽世,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布挚赊,位于F島的核電站,受9級特大地震影響济瓢,放射性物質(zhì)發(fā)生泄漏荠割。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔑鹦。 院中可真熱鬧夺克,春花似錦、人聲如沸嚎朽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哟忍。三九已至狡门,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锅很,已是汗流浹背其馏。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爆安,地道東北人叛复。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像扔仓,于是被迫代替她去往敵國和親褐奥。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355