關(guān)于在.net Core使用iTextsharp導(dǎo)出pdf

前言:這兩個星期一直在弄在Core上導(dǎo)出pdf文件没龙,并且pdf文件是屬于比較復(fù)雜铺厨,所以需要用到模板來填充數(shù)據(jù),遇到了很多的問題硬纤!

  • 使用的是Core,iTextsharp最新的版本5.x與之不兼容解滓,并且最新的版本已經(jīng)不開源了,商業(yè)用途需要收費的筝家。
  • 我使用的是版本4.x洼裤,還是零幾年的一個版本。這個版本有一個問題就是凡是編碼的字體都會嵌入到pdf中溪王,所以一個原本只有幾十k大小的pdf變成了4m多腮鞍,而且這只是一個pdf值骇,如果有批量導(dǎo)出的話,五十個就是幾百m了移国,可怕吱瘩!
  • 最關(guān)鍵的是所有的注釋全部都是英文,而且是一段落一段落的迹缀,而且相關(guān)的問題百度到的壓根沒有參考價值使碾,只能去stackoverflow找答案,看的腦子都漿糊了...

所以在此將我所遇到的一些坑記錄一下祝懂,防止有人重走我的老路票摇!


詳細步驟

pdf模板制作

下載adobe acrobat pro這個軟件,當(dāng)然是收費么砚蓬,不過我大天朝嘛(ps:大家有錢的還是要支持支持正版呀矢门,當(dāng)然我很窮。)然后打開一個pdf文檔灰蛙,點擊導(dǎo)航欄的表單祟剔,可以看到有很多選項:表單向?qū)亲詣訋湍氵x擇區(qū)域(將空白的部分劃分成一個區(qū)域),你也可以自己添加區(qū)域來編輯缕允。類似下圖峡扩,那一個一個藍色的就是一個一個區(qū)域蹭越,回頭可以直接賦值的

模板區(qū)域制作

pdf模板賦值

  • 首先需要導(dǎo)入iTextsharp這個庫障本,如果你不是Core的話直接導(dǎo)入最新版本就好了,如果你用Core的話我在里面貌似沒找到5.x之前的版本响鹃,我導(dǎo)的是iTextSharp.LGPLv2.Core,這是伊朗的一位C#開發(fā)者封裝的一個工具類驾霜。

  • 導(dǎo)入庫之后就可以來對模板進行賦值,代碼如下

     //獲取中文字體,第三個參數(shù)表示為是否潛入字體,但只要是編碼字體就都會嵌入。
     BaseFont baseFont = BaseFont.CreateFont(@"C:\Windows\Fonts\simsun.ttc,1",BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
     //讀取模板文件
     PdfReader reader = new PdfReader(@"C:\Users\Administrator\Desktop\template.pdf");
    
     //創(chuàng)建文件流用來保存填充模板后的文件
     MemoryStream stream = new MemoryStream();
             
     PdfStamper stamp = new PdfStamper(reader, stream);
     //設(shè)置表單字體死讹,在高版本有用蛔屹,高版本加入這句話就不會插入字體,低版本無用
     //stamp.AcroFields.AddSubstitutionFont(baseFont);
    
     AcroFields form = stamp.AcroFields;
    
     //表單文本框是否鎖定
     stamp.FormFlattening = true;
    
     //填充表單,para為表單的一個(屬性-值)字典
     foreach (KeyValuePair<string, string> parameter in para)
     {
         //要輸入中文就要設(shè)置域的字體;
         form.SetFieldProperty(parameter.Key, "textfont", baseFont, null);
         //為需要賦值的域設(shè)置值;
          form.SetField(parameter.Key, parameter.Value);
      }
    

    還可以對模板添加圖片烘浦,代碼如下

    // 通過域名獲取所在頁和坐標(biāo),左下角為起點
    float[] positions = form.GetFieldPositions("sender");
    int pageNo = (int)positions[0];
    float x = positions[1];
    float y = positions[2];
    // 讀圖片
    Image image = Image.GetInstance(@"C:\Users\Administrator\Desktop\02.png");
    // 獲取操作的頁面
    PdfContentByte under = stamp.GetOverContent(pageNo);
    // 根據(jù)域的大小縮放圖片
    image.ScaleToFit(positions[3] - positions[1], positions[4] - positions[2]);
    // 添加圖片
    image.SetAbsolutePosition(x, y);
    under.AddImage(image);
    
  這里大家可能對**positions**不太了解,他的注釋:

>Gets the field box positions in the document. The return >is an array of float multiple of 5. For each of this groups the values are: [page, llx, lly, urx, ury]. The coordinates have the page rotation in consideration.


大概意思就是獲取pdf一個域的坐標(biāo)寞酿,返回了一個數(shù)組,盛放的分別是:[當(dāng)前是第幾頁]脱柱,[區(qū)域左下方的X坐標(biāo)]伐弹,[區(qū)域左下方的Y坐標(biāo)],[區(qū)域右上方的X坐標(biāo)]榨为,[區(qū)域右上方的Y坐標(biāo)]惨好。通過四個點就知道這塊區(qū)域的大小煌茴,然后再定位到是第幾頁。(語文水平不太高日川,聽不懂就.....see more times)



最后按順序關(guān)閉io流

    stamp.Close();
    reader.Close();

這里是單個模板賦值蔓腐,單個模板生成多個pdf就加個for循環(huán)就好,多個模板的話也差不多龄句,單個模板搞定了合住,其他都簡單了


合并生成的多個pdf文件

在上面我這里沒有生成pdf文件,而是用MemoryStream將賦值完成的pdf放到了內(nèi)存中撒璧,然后再將他們合并發(fā)送到客戶端直接下載透葛,這樣就避免了許多的文件io操作,提升點效率卿樱。(當(dāng)然如果文件太多太大的話可能會內(nèi)存溢出而掛掉吧)

代碼如下:

Document document = new Document();

//將合并后的pdf依舊以流的方式保存在內(nèi)存中
MemoryStream mergePdfStream = new MemoryStream();

//這里用的是smartCopy僚害,整篇文檔只會導(dǎo)入一份字體。屬于可接受范圍內(nèi)
PdfSmartCopy copy = new PdfSmartCopy(document, mergePdfStream);

document.Open();

for (int i = 0; i < pdfStreams.Count; i++)
{
   for循環(huán)讀取之前生成的單個pdf字節(jié)數(shù)組繁调,這里將流保存在數(shù)組中傳遞過來使用的話不行萨蚕,會報錯,我也不知道為什么蹄胰,所以用了字節(jié)數(shù)組(如果有人知道的話還請告訴我岳遥,不勝感激)
   byte[] stream = pdfStreams[i];
   PdfReader reader = new PdfReader(stream);

   //for循環(huán)新增文檔頁數(shù),并copy pdf數(shù)據(jù)
   document.NewPage();
   PdfImportedPage imported = copy.GetImportedPage(reader, 1);
   copy.AddPage(imported);

    reader.Close();
 }
 copy.Close();
 document.Close();

 //這里將合并后的pdf流傳出去裕寨,方法我沒全復(fù)制過來浩蓉。(你們也不能光復(fù)制就想著直接用吧,好歹動下頭腦)
 return mergePdfStream;

pdf在瀏覽器中下載

這是最后一步了宾袜,我用的是MVC,不過不管用什么都一樣的原理

FileResult fileResult = new FileContentResult(mergePdfStream.ToArray(), "application/pdf");
fileResult.FileDownloadName = "4.pdf";

然后直接返回fileResult就行捻艳,因為它是繼承于ActionResult的,應(yīng)該是MVC框架的一個專門返回文件的類庆猫。(.net就是爽认轨,微軟封裝的太好了)


and最終

趁還在,多陪陪身邊的人月培,莫等到失去才開始后悔嘁字。

另外廈門是個好地方!


聯(lián)系方式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纪蜒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子寻行,更是在濱河造成了極大的恐慌霍掺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異杆烁,居然都是意外死亡牙丽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門兔魂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烤芦,“玉大人,你說我怎么就攤上這事析校」孤蓿” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵智玻,是天一觀的道長遂唧。 經(jīng)常有香客問我,道長吊奢,這世上最難降的妖魔是什么盖彭? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮页滚,結(jié)果婚禮上召边,老公的妹妹穿的比我還像新娘。我一直安慰自己裹驰,他們只是感情好隧熙,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幻林,像睡著了一般贞盯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上滋将,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天邻悬,我揣著相機與錄音症昏,去河邊找鬼随闽。 笑死,一個胖子當(dāng)著我的面吹牛肝谭,可吹牛的內(nèi)容都是我干的掘宪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼攘烛,長吁一口氣:“原來是場噩夢啊……” “哼魏滚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坟漱,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鼠次,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腥寇,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡成翩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了赦役。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麻敌。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖掂摔,靈堂內(nèi)的尸體忽然破棺而出术羔,到底是詐尸還是另有隱情,我是刑警寧澤乙漓,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布级历,位于F島的核電站,受9級特大地震影響叭披,放射性物質(zhì)發(fā)生泄漏鱼喉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一趋观、第九天 我趴在偏房一處隱蔽的房頂上張望扛禽。 院中可真熱鬧,春花似錦皱坛、人聲如沸编曼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掐场。三九已至,卻和暖如春贩猎,著一層夾襖步出監(jiān)牢的瞬間熊户,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工吭服, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嚷堡,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓艇棕,卻偏偏與公主長得像蝌戒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沼琉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容