Search code examples
c#pdfitext

iTextSharp merge pdfs with bookmarks


I am trying to Combine pdfs and create bookmarks for those PDFs. If I start the merger with a pdf that already has bookmarks this code works fine. However if I start with a single paged pdf with no bookmarks it does not work at all.

using (PdfCopy pdf = new PdfCopy(doc, stream))
{
doc.Open();


PdfReader reader = null;
PdfImportedPage page = null;
var outlines = new List<Dictionary<string, object>>();
int pageIndex = 1;
InFiles.ForEach(Filenm =>
{
    if (Path.GetExtension(Filenm) == ".pdf")
    {
        if (Path.GetFullPath(Filenm) != Path.GetFullPath(OutFile))
        {                                       
            reader = new PdfReader(Filenm);
            IList<Dictionary<string, object>> book_mark = SimpleBookmark.GetBookmark(reader);
            for (int i = 0; i < reader.NumberOfPages; i++)
            {                                            
                page = pdf.GetImportedPage(reader, i + 1);
                if (book_mark != null)
                {
                    var mark = book_mark[pageIndex - 1];
                    mark["Page"] = pageIndex + " FitH -4";
                    mark["Action"] = "GoTo";                                                
                    outlines.Add(mark);
                }
                else
                { 
                    var mark = new Dictionary<string, object>();
                    mark["Title"] = Path.GetFileNameWithoutExtension(Filenm);
                    mark["Page"] = pageIndex + " FitH -4";
                    mark["Action"] = "GoTo";                                                
                    outlines.Add(mark);
                }
                pdf.AddPage(page);
                pageIndex++;
            }

            pdf.FreeReader(reader);
            reader.Close();

        }
    }
});
pdf.Outlines = outlines;

}


Solution

  • We can move the bookmark outside the loop and add validation creating bookmark

    using (PdfCopy pdf = new PdfCopy(doc, stream))
    {
        doc.Open();
        
        PdfReader reader = null;
        PdfImportedPage page = null;
        var outlines = new List<Dictionary<string, object>>();
        int pageIndex = 1;
    
        InFiles.ForEach(Filenm =>
        {
            if (Path.GetExtension(Filenm) == ".pdf")
            {
                if (Path.GetFullPath(Filenm) != Path.GetFullPath(OutFile))
                {
                    reader = new PdfReader(Filenm);
                    
                    // Retrieve bookmarks for the entire PDF once, not per page
                    IList<Dictionary<string, object>> book_mark = SimpleBookmark.GetBookmark(reader);
                    
                    for (int i = 0; i < reader.NumberOfPages; i++)
                    {
                        page = pdf.GetImportedPage(reader, i + 1);
                        
                        if (book_mark != null && i < book_mark.Count)
                        {
                            var mark = book_mark[i];
                            mark["Page"] = pageIndex + " FitH -4";
                            mark["Action"] = "GoTo";
                            outlines.Add(mark);
                        }
                        else
                        {
                            var mark = new Dictionary<string, object>();
                            mark["Title"] = Path.GetFileNameWithoutExtension(Filenm);
                            mark["Page"] = pageIndex + " FitH -4";
                            mark["Action"] = "GoTo";
                            outlines.Add(mark);
                        }
                        
                        pdf.AddPage(page);
                        pageIndex++;
                    }
    
                    pdf.FreeReader(reader);
                    reader.Close();
                }
            }
        });
    
        pdf.Outlines = outlines;
    }