C#藉由iTextSharp來達成多個PDF合併處裡_三異常排除
PDF合併的功能程式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using iTextSharp.text; using iTextSharp.text.pdf; namespace EPOOPS_Scheduler.App_Code.Public.Utility { class PdfHelper { #region "private field" private Font _font; private Rectangle _rect; private Document _document; private BaseFont _baseFont; #endregion public PdfHelper() { } public PdfHelper(string type) { SetPageSize(type); _document = new Document(_rect); } public void Open(Stream stream) { PdfWriter.GetInstance(_document, stream); _document.Open(); } public void Close() { _document.Close(); } public void SetPageSize(string type) { switch (type.Trim()) { case "A4": _rect = PageSize.A4; break; case "A8": _rect = PageSize.A8; break; } } public void SetFont(float size) { _font = new Font(_baseFont, size); } /// <summary> /// 合併多個pdf檔案 /// </summary> /// <param name="lsPdfFile">目標要合併的pdf文件</param> /// <param name="mergedFile">最終存出合併pdf</param> /// <param name="isVertical">是否要直印,預設為直印</param> public static void MergePdfFiles(List<string> lsPdfFile, string mergedFile, bool isVertical = true) { PdfReader reader; Document document = new Document(); if (!isVertical) { document = new Document(iTextSharp.text.PageSize.A4.Rotate()); } PdfWriter writer = null; writer = PdfWriter.GetInstance(document, new FileStream(mergedFile, FileMode.Create)); document.Open(); PdfContentByte cb = writer.DirectContent; PdfImportedPage newPage; for (int i = 0; i < lsPdfFile.Count; i++) { if (lsPdfFile[i] != null && lsPdfFile[i] != string.Empty) { reader = new PdfReader(lsPdfFile[i]); int iPageNum = reader.NumberOfPages; for (int j = 1; j <= iPageNum; j++) { document.NewPage(); newPage = writer.GetImportedPage(reader, j); //reader.Close(); //reader.Dispose(); cb.AddTemplate(newPage, 0, 0); } writer.FreeReader(reader); reader.Close(); reader.Dispose(); } } document.Close(); } } } |
這裡要注意
若你是跟我一樣參考這一篇作者寫的方式
C# 利用iTextSharp合併pdf
http://noteofisabella.blogspot.com/2019/03/c-itextsharppdf.html
可能要在調整因為iTextSharp 本身API內部會throw出null 的例外
而且是try catch也無法捕獲處理的
可參考這一篇處理
PdfWriter.GetInstance throws System.NullReferenceException
https://stackoverflow.com/questions/15833285/pdfwriter-getinstance-throws-system-nullreferenceexception
將例外跳出的勾選給勾消就不會因為其API本身於runtime拋出例外而有困擾
由於我需求功能本身涉及到要把call api 返回的byte array轉為PDF並下載一頁頁PDF來合併
落地處理
最終生成的一頁頁要做刪除
此時發現一個錯誤在刪除檔案時
沒錯後來藉由此篇教學我發現是合併PDF函數
圓心參考到的這一篇作者
寫的方式有BUG要在改善....
有資源沒有做好Close跟Dispose
然而就在你直接對reader直接Close跟Dispose時又出現一個離奇異常
Can't dispose PdfReader without disposing Document and PdfWriter....
原因在於iTextSharp API好像有限制在PdfReader被Dispose之前必須
也將Document資源釋放而使得比較沒這麼自由彈性
所以需要在藉由這一篇解法分享
Can't dispose PdfReader without disposing Document and PdfWriter
調用PdfWriter的 FreeReader方法來讓iText不會多做沒必要的資源拷貝
https://afterlogic.com/mailbee-net/docs-itextsharp/
參考:
C# 利用iTextSharp合併pdf
PdfWriter.GetInstance throws System.NullReferenceException
iTextSharp issues wherein null reference exception
Merging multiple PDFs using iTextSharp in c#.net
Can't dispose PdfReader without disposing Document and PdfWriter
Create PDFs in ASP.NET - getting started with iTextSharp
留言
張貼留言