Skip to main content
Skip table of contents

Merging documents with bookmarks

This example was written in answer to the question Click How to merge PDFs and add bookmarks?


mergewithoutlines

JAVA

JAVA
/**
 * Example written by Bruno Lowagie in answer to a question on StackOverflow
 * 
 * When concatenating documents, we add a named destination every time
 * a new document is started. After we've finished merging, we add an extra
 * page with the table of contents and links to the named destinations.
 */
package sandbox.merge;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import sandbox.WrapToTest;

@WrapToTest
public class MergeWithOutlines {

    public static final String SRC1 = "resources/pdfs/hello.pdf";
    public static final String SRC2 = "resources/pdfs/links1.pdf";
    public static final String SRC3 = "resources/pdfs/links2.pdf";
    public static final String DEST = "results/merge/merge_with_outlines.pdf";
    
    public Map<String, PdfReader> filesToMerge;
    
    public static void main(String[] args) throws IOException, DocumentException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new MergeWithOutlines().createPdf(DEST);
    }
    
    
    public void createPdf(String filename) throws IOException, DocumentException {
        Document document = new Document();
        PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
        document.open();
        int page = 1;
        ArrayList<HashMap<String, Object>> outlines = new ArrayList<HashMap<String, Object>>();
        // add the first document
        PdfReader reader1 = new PdfReader(SRC1);
        copy.addDocument(reader1);
        // add the first outline element
        HashMap<String, Object> helloworld = new HashMap<String, Object>();
        helloworld.put("Title", "Hello World");
        helloworld.put("Action", "GoTo");
        helloworld.put("Page", String.format("%d Fit", page));
        outlines.add(helloworld);
        // update page count
        page += reader1.getNumberOfPages();
        // add the second document
        PdfReader reader2 = new PdfReader(SRC2);
        copy.addDocument(reader2);
        // add the second outline element as a kid of the first one
        ArrayList<HashMap<String, Object>> kids = new ArrayList<HashMap<String, Object>>();
        HashMap<String, Object> link1 = new HashMap<String, Object>();
        link1.put("Title", "link1");
        link1.put("Action", "GoTo");
        link1.put("Page", String.format("%d Fit", page));
        kids.add(link1);
        helloworld.put("Kids", kids);
        // update page count
        page += reader2.getNumberOfPages();
        // add the third document
        PdfReader reader3 = new PdfReader(SRC3);
        copy.addDocument(reader3);
        // add the third outline element to the root
        HashMap<String, Object> link2 = new HashMap<String, Object>();
        link2.put("Title", "Link 2");
        link2.put("Action", "GoTo");
        link2.put("Page", String.format("%d Fit", page));
        outlines.add(link2);
        // add the outlines
        copy.setOutlines(outlines);
        // close the document
        document.close();
        reader1.close();
        reader2.close();
        reader3.close();
    }
}


insertandadaptoutlines

JAVA

JAVA
/*
 * Example written in answer to:
 * http://stackoverflow.com/questions/34381849
 */
package sandbox.merge;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.SimpleBookmark;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import sandbox.WrapToTest;

@WrapToTest
public class InsertAndAdaptOutlines {

    /** The original PDF file. */
    public static final String INSERT
        = "resources/pdfs/hello.pdf";
    /** The original PDF file. */
    public static final String SRC
        = "resources/pdfs/bookmarks.pdf";
    /** The resulting PDF file. */
    public static final String DEST
        = "results/merge/bookmarks_hello.pdf";
    
    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new InsertAndAdaptOutlines().manipulatePdf(SRC, DEST);
    }
    
    /**
     * Manipulates a PDF file src with the file dest as result
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     */
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException {
        PdfReader insert = new PdfReader(INSERT);
        PdfReader reader = new PdfReader(src);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST));
        stamper.insertPage(4, insert.getPageSize(1));
        PdfContentByte cb = stamper.getOverContent(4);
        cb.addTemplate(stamper.getImportedPage(insert, 1), 0, 0);
        List<HashMap<String, Object>> outlines = SimpleBookmark.getBookmark(reader);
        HashMap<String, Object> entry = new HashMap<String, Object>();
        entry.put("Title", "Hello");
        entry.put("Action", "GoTo");
        entry.put("Page", "4 Fit");
        updateOutline(outlines, entry, 4);
        stamper.setOutlines(outlines);
        stamper.close();
    }
    
    public boolean updateOutline(List<HashMap<String, Object>> outlines, HashMap<String, Object> entry, int p) {
        int index = 0;
        for (HashMap<String, Object> outline : outlines) {
            Object kids = outline.get("Kids");
            if (kids != null) {
                updateOutline((List<HashMap<String, Object>>)kids, entry, p);
            }
            else {
                if (p < getPage(outline)) {
                    outlines.add(index, entry);
                    return true;
                }
                index++;
            }
        }
        return false;
    }
    
    public int getPage(HashMap<String, Object> outline) {
        Object page = outline.get("Page");
        if (page == null) return -1;
        String p = page.toString().substring(0, page.toString().indexOf(" "));
        return Integer.parseInt(p);
    }
}
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.