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資源釋放而使得比較沒這麼自由彈性

所以需要在藉由這一篇解法分享

調用PdfWriter的 FreeReader方法來讓iText不會多做沒必要的資源拷貝

https://afterlogic.com/mailbee-net/docs-itextsharp/



參考:
C# 利用iTextSharp合併pdf




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


留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header