2016-01-05 6 views
1

У меня есть процесс, который объединяет несколько PDF-файлов в один PDF-файл. Это отлично работает.Вставить PieceInfo в объединенный документ с ITextSharp

Во время слияния я хочу добавить PieceInfo на уровне страницы, чтобы отслеживать документы, которые были включены в этот объединенный файл.

Предположим, у меня есть 3 документа в этом порядке: Fester.pdf (2 страницы), Gomez.pdf (2 страницы) и Lurch.pdf (1 страница). После слияния у меня будет 5 страниц, и каждая страница будет иметь PieceInfo с именем файла, из которого был создан. Таким образом, если я перейду на страницу 4, я узнаю, что страница была создана из Gomez.pdf

Во время моего поиска я нашел это сообщение: Insert hidden digest in pdf using iText library, и я попытался реализовать то же самое в моем процессе. Предложение работает отлично, но я не мог понять, как хранить информацию на странице.

Вот мой код:

public static byte[] MergeDocuments(DocumentCollection myCollection) 
{ 
    PdfImportedPage importedPage = null; 

    // Merged the document streams 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     // Create the iTextSharp document 
     iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(); 

     // Create the PDF writer that listened to the document 
     PdfCopy pdfCopy = new PdfCopy(pdfDoc, stream); 
     if (pdfDoc != null && pdfCopy != null) 
     { 
      // Open the document and load content 
      pdfDoc.Open(); 

      //Dictionary Entries 
      PdfName appName = new PdfName("MyKey"); 
      PdfName dataName = new PdfName("Hash"); 

      //Class to add and retrieve the PieceInfo data 
      DocumentPieceInfo dpi = new DocumentPieceInfo(); 

      //Loop through my collection. The document class has the BinaryFile and FileName 
      foreach (Document doc in myCollection) 
      { 
       PdfReader reader = new PdfReader(doc.FileBinary); 
       if (reader != null) 
       { 
        int nPage = reader.NumberOfPages; 
        for (int n = 0; n < nPage; n++) 
        { 
         //Trying to add the PieceInfo 
         dpi.addPieceInfo(pdfCopy, appName, dataName, new PdfString(string.Format("Info Doc: {0}", doc.FileName))); 
         importedPage = pdfCopy.GetImportedPage(reader, n + 1); 
         pdfCopy.AddPage(importedPage); 
        } 
        // Close the reader 
        reader.Close(); 
       } 
      } 

      if (pdfCopy != null) 
       pdfCopy.Close(); 

      if (pdfDoc != null) 
       pdfDoc.Close(); 

      byte[] arrOutput = stream.ToArray(); 
      return arrOutput; 

     } 
    } 
    return null; 
} 

И небольшое изменение в решение MKL, меняя вход в PDFCopy:

public void addPieceInfo(PdfCopy reader, PdfName app, PdfName name, PdfObject value) 
    { 
     //PdfDictionary catalog = reader.getCatalog(); 
     PdfDictionary pieceInfo = reader.ExtraCatalog.GetAsDict(PIECE_INFO); 
     if (pieceInfo == null) 
     { 
      pieceInfo = new PdfDictionary(); 
      reader.ExtraCatalog.Put(PIECE_INFO, pieceInfo); 
     } 

     PdfDictionary appData = pieceInfo.GetAsDict(app); 
     if (appData == null) 
     { 
      appData = new PdfDictionary(); 
      pieceInfo.Put(app, appData); 
     } 

     PdfDictionary privateData = appData.GetAsDict(PRIVATE); 
     if (privateData == null) 
     { 
      privateData = new PdfDictionary(); 
      appData.Put(PRIVATE, privateData); 
     } 

     appData.Put(LAST_MODIFIED, new PdfDate()); 
     privateData.Put(name, value); 
    } 

Код выше добавления pieceinfo на последней странице только :(

ли объект страницы PdfImportedPage есть способ получить каталог?

Как включить эту информацию на уровень страницы во время моего процесса слияния? После этого, как я могу получить часть информации со страниц? Просто перебираете страницы?

+0

Класс «DocumentPieceInfo» из моего старого ответа работает только со структурой * Document-wide * ** PieceInfo **. Если вы хотите разместить информацию на каждой странице, имя для этой информации должно каким-то образом включать страницу, например. 'new PdfName (« Хеш »+ номер страницы)'. Поскольку страницы в документе могут быть позже удалены или вставлены, это не является оптимальным. Вам лучше использовать * page-level * ** PieceInfo ** структуры или (из-за неминуемой ** PieceInfo ** устаревания) * на уровне страницы * личные ключи, зарегистрированные вам, ср. @Brunos abswer. – mkl

ответ

0

Обратите внимание: /PieceInfo будет устаревшим в ISO-32000-2 (aka PDF 2.0). В качестве альтернативы вы можете создать свой собственный ключ, чтобы добавить свои собственные данные. Это объясняется в моем ответе на вопрос itext how to check if giant string is present on the pdf page.

Вы спрашиваете Имеет ли страница PdfImportedPage объект для получения каталога?

Это неправильный вопрос. Если вы хорошо изучите my answer, вы обнаружите, что вам нужен доступ к словарю страницы. Вы можете добавить запись /PieceInfo (или свою собственную запись) на эту страницу, а затем получить ее.

Посмотрите на CustomPageDictKeyMerge:

public void createPdf(String filename) throws IOException, DocumentException { 
    PdfName marker = new PdfName("ITXT_PageMarker"); 
    List<PdfReader> readers = new ArrayList<PdfReader>(); 
    readers.add(new PdfReader(SRC1)); 
    readers.add(new PdfReader(SRC2)); 
    readers.add(new PdfReader(SRC3)); 
    Document document = new Document(); 
    PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename)); 
    document.open(); 
    int counter = 0; 
    int n; 
    PdfImportedPage importedPage; 
    PdfDictionary pageDict; 
    for (PdfReader reader : readers) { 
     counter++; 
     n = reader.getNumberOfPages(); 
     for (int p = 1; p <= n; p++) { 
      pageDict = reader.getPageN(p); 
      pageDict.put(marker, new PdfString(String.format("Page %s of document %s", p, counter))); 
      importedPage = copy.getImportedPage(reader, p); 
      copy.addPage(importedPage); 
     } 
    } 
    // close the document 
    document.close(); 
    for (PdfReader reader : readers) { 
     reader.close(); 
    } 
} 

В этом примере мы добавляем специальный маркер словаря страницы, прежде чем импортировать страницу. В результате, этот маркер будет добавлен в объединенном документе:

enter image description here

Взгляните на CustomPageDictKeyCreate Например, чтобы узнать, как получить эти пользовательские маркеры:

public void check(String filename) throws IOException { 
    PdfReader reader = new PdfReader(filename); 
    PdfDictionary pagedict; 
    for (int i = 1; i < reader.getNumberOfPages(); i++) { 
     pagedict = reader.getPageN(i); 
     System.out.println(pagedict.get(new PdfName("ITXT_PageMarker"))); 
    } 
    reader.close(); 
} 

Пожалуйста, убедитесь, что вы используете имя второго класса для своего пользовательского ключа. iText зарегистрировал префикс ITXT с ISO для своих пользовательских ключей второго класса. Этот префикс гарантирует, что разные компании не используют один и тот же ключ для разных целей.Все ключи, начинающиеся с ITXT, могут быть легко идентифицированы как ключи, созданные iText Group. ISO отслеживает все эти префиксы, чтобы избежать дублирования. Регистрация префикса с ISO бесплатна.

+0

Привет, Бруно, благодарю вас за ваше предложение. Прошу прощения, но у меня еще не было времени проверить это. Надеюсь, я проведу это в выходные. Что это инструмент, который вы используете для просмотра структуры PDF? :) – UncleFester

+0

@UncleFester Этот инструмент называется [iText RUPS] (http://itextpdf.com/Products/itext-rups) –

Смежные вопросы