ShiftPageNumbers与iTextSharp [英] ShiftPageNumbers with iTextSharp

查看:147
本文介绍了ShiftPageNumbers与iTextSharp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用iTextSharp合并某些PDF同时保留书签时遇到了一些麻烦。我编写了以下hackish代码来测试一个想法,但ShiftPageNumbers方法似乎甚至不适合我。有没有人知道为什么?

I'm having some trouble using iTextSharp to merge some PDFs while preserving the bookmarks. I've written the following hackish code to test an idea, but the ShiftPageNumbers method doesn't seem to even be working for me. Does anyone have any idea why?

string[] files = Directory.GetFiles(folder);
string path = Path.GetDirectoryName(files[0]);
IList<Dictionary<string, object>> oldBookmarks
    = SimpleBookmark.GetBookmark(new PdfReader(files[0]));
List<Dictionary<string, object>> newBookmarks = new List<Dictionary<string, object>>();

FileStream outFile = new FileStream(output, FileMode.Create);
PdfConcatenate newPdf = new PdfConcatenate(outFile);

switch (oldBookmarks.Count())
{
    case 0:
        break;

    case 1:
        oldBookmarks = (IList<Dictionary<string, object>>)(oldBookmarks[0])["Kids"];
        break;

    default:
        break;
}

files = oldBookmarks.Select(b => b["File"]).Cast<string>().ToArray();

foreach (string filename in files)
{
    Console.Write:ine(filename);
    PdfReader reader = new PdfReader(Path.Combine(path, filename));
    newPdf.AddPages(reader);

    List<Dictionary<string, object>> tempBookmarks =
        oldBookmarks.Where(b => (string)b["File"] == filename).ToList();

    // handles bookmarks
    SimpleBookmark.ShiftPageNumbers(tempBookmarks, length, null);
    newBookmarks.AddRange(tempBookmarks);
    length += reader.NumberOfPages;

    reader.Close();
}

newPdf.Writer.Outlines = newBookmarks;
newPdf.Close();


推荐答案

最后,我结束了使用递归函数调整页码。我认为如果我只是包含整个应用程序的代码,这是最简单的。该程序旨在编辑美国无线电中继联盟(ARRL)出版的电子书,这些电子书分为许多PDF,这些PDF都包含相同的书签列表。每个第一级书签及其子项链接到不同的PDF文件。因此,标准PDF合并程序将无法正确保留书签。

In the end, I wound up using a recursive function to adjust the page numbers. I figured it was easiest to show if I simply included the code for the entire application. This program is designed to compile eBooks published by the American Radio Relay League (ARRL), which are broken up into many PDFs that all contain the same list of bookmarks. Each first-level bookmark and its children link to a different PDF file. Therefore, a standard PDF merging program will not correctly preserve the bookmarks.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using iTextSharp.text.pdf;

namespace ARRL_Book_Compiler
{
    internal class Program
    {
        private const string ACTION_KEY = "Action";
        private const string FILE_KEY = "File";
        private const string KIDS_KEY = "Kids";
        private const string PAGE_KEY = "Page";
        private const char DELIM = ' ';

        private static void Main(string[] args)
        {
            if (args.Count() != 2)
            {
                Console.WriteLine("Arg 1: PDF directory");
                Console.WriteLine("Arg 2: Output filename");
                Environment.Exit(1);
            }

            Merge(args[0], args[1]);
        }

        /// <summary>
        /// Compiles ARRL books.
        /// </summary>
        /// <param name="folder">Directory containing all the PDFs in the entire book.</param>
        /// <param name="output">Path and filename of the output (compiled) PDF.</param>
        private static void Merge(string folder, string output)
        {
            int offset = 1;  // Setting to 0 causes all bookmarks to be off by 1
            string[] dirFiles
                = Directory.GetFiles(folder).Where(f => f.EndsWith("pdf")).ToArray();  // PDFs in directory
            IList<Dictionary<string, object>> oldBookmarks
                = SimpleBookmark.GetBookmark(new PdfReader(dirFiles[0]));
            List<Dictionary<string, object>> newBookmarks = new List<Dictionary<string, object>>();

            FileStream outFile = new FileStream(output, FileMode.Create);
            PdfConcatenate newPdf = new PdfConcatenate(outFile);

            if (oldBookmarks.Count() == 1)
            {
                oldBookmarks = (IList<Dictionary<string, object>>)(oldBookmarks[0])[KIDS_KEY];
            }

            string[] bFiles
                = oldBookmarks.Select(b => b[FILE_KEY]).Cast<string>().ToArray();  // get files in bookmark order
            IEnumerable<string> missingFiles = bFiles.Except(dirFiles.Select(f => Path.GetFileName(f)));

            if (missingFiles.Any())
            {
                Console.Error.WriteLine("The following files are present in the bookmarks but not in the directory:");
                foreach (string filename in missingFiles) Console.Error.WriteLine(filename);
                Environment.Exit(2);
            }

            for(int i = 0; i < bFiles.Count(); i++)
            {
                Console.Write(string.Format("\r{0}% complete", (int)((i + 1f)/bFiles.Count()*100)));
                string filename = bFiles[i];
                PdfReader reader = new PdfReader(Path.Combine(folder, filename));
                List<Dictionary<string, object>> tempBookmarks =
                    oldBookmarks.Where(b => b.ContainsKey(FILE_KEY) && (string)b[FILE_KEY] == filename).ToList();

                // handles bookmarks
                newBookmarks.AddRange(ModifyBookmarks(  // Exception if LINQ can't find FILE_KEY key in ANY list item
                    oldBookmarks.Where(b => b.ContainsKey(FILE_KEY) && (string)b[FILE_KEY] == filename).ToList(),
                    offset));
                offset += reader.NumberOfPages;

                newPdf.AddPages(reader);
                reader.Close();
            }

            newPdf.Writer.Outlines = newBookmarks;
            newPdf.Close();
        }

        private static List<Dictionary<string, object>>
            ModifyBookmarks(List<Dictionary<string, object>> list, int offset)
        {
            for (int i = 0; i < list.Count(); i++)
            {
                string pageKey = (string)list[i][PAGE_KEY];
                int index = pageKey.IndexOf(DELIM);
                list[i][PAGE_KEY] = (int.Parse(pageKey.Substring(0, index)) + offset).ToString()
                    + pageKey.Substring(index);

                if (list[i].ContainsKey(FILE_KEY)) list[i].Remove(FILE_KEY);
                if (list[i].ContainsKey(ACTION_KEY)) list[i][ACTION_KEY] = "GoTo";

                if (list[i].ContainsKey(KIDS_KEY))
                    list[i][KIDS_KEY] = ModifyBookmarks((List<Dictionary<string, object>>)list[i][KIDS_KEY], offset);
            }

            return list;
        }
    }
}

这篇关于ShiftPageNumbers与iTextSharp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆