I need to create a TOC (not bookmarks) at the beginning of this document with clickable links to the first pages of each of the source PDFs.
I'm doing the following:
Document document = new Document(); PdfCopy copy = new PdfCopy(document, outputStream); PdfCopy.PageStamp stamp; document.open(); PdfReader reader; <ListInputStream> pdfs = streamOfPDFFiles; <ListPdfReader> readers = new ArrayListPdfReader>(); <IteratorInputStream> iteratorPDFs = pdfs.iterator(); for (; iteratorPDFs.hasNext(); pdfCounter++) { InputStream pdf = iteratorPDFs.next(); reader = new PdfReader(pdf); readers.add(reader); pdf.close(); } int currentPageNumber = 0; <IteratorPdfReader> readerIterator = readers.iterator(); PdfImportedPage page; int count = 1; while (readerIterator.hasNext()) { reader = readerIterator.next(); count++; int number_of_pages = reader.getNumberOfPages(); for (int pageNum = 0; pageNum number_of_pages;) { currentPageNumber++; page = copy.getImportedPage(reader, ++pageNum); ColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_RIGHT, new Phrase( String.format("%d", currentPageNumber), new Font(FontFamily.TIMES_ROMAN,3)), 50, 50, 0); stamp.alterContents(); copy.addPage(page); } } document.close();
Posted on StackOverflow on
Feb 4, 2014
by
Butani Vijay
You're asking for something that should be trivial, but that isn't. Please take a look at the MergeWithToc example. You'll see that your code to merge PDFs is correct, but in my example, I added one extra feature:
chunk = new Chunk(String.format("Page %d", pageNo)); if (i == 1) chunk.setLocalDestination("p" + pageNo); ColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_RIGHT, new Phrase(chunk), 559, 810, 0);
For every first page, I define a named destination as a local destination. We use p followed by the page number as its name.
We'll use these named destinations in an extra page that will serve as a TOC:
PdfReader reader = new PdfReader(SRC3); page = copy.getImportedPage(reader, 1); stamp = copy.createPageStamp(page); Paragraph p; PdfAction action; PdfAnnotation link; float y = 770; ColumnText ct = new ColumnText(stamp.getOverContent()); ct.setSimpleColumn(36, 36, 559, y); for (Map.Entry entry : toc.entrySet()) { p = new Paragraph(entry.getValue()); p.add(new Chunk(new DottedLineSeparator())); p.add(String.valueOf(entry.getKey())); ct.addElement(p); ct.go(); action = PdfAction.gotoLocalPage("p" + entry.getKey(), false); link = new PdfAnnotation(copy, 36, ct.getYLine(), 559, y, action); stamp.addAnnotation(link); y = ct.getYLine(); } ct.go(); stamp.alterContents(); copy.addPage(page);
In my example, I assume that the TOC fits on a single page. You'll have to keep track of the y value and create a new page if its value is lower than the bottom margin.
If you want the TOC to be the first page, you need to reorder the pages in a second go. This is shown in the MergeWithToc2 example:
reader = new PdfReader(baos.toByteArray()); n = reader.getNumberOfPages(); reader.selectPages(String.format("%d, 1-%d", n, n-1)); PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(filename)); stamper.close();