将页面添加为第n页

时间:2015-12-20 14:09:39

标签: java pdf itext

我有两个pdf:

  1. Master.pdf:包含带书签的页面,大纲(目录)。
  2. Child.pdf:包含单页的文件。
  3. Child.pdf页面需要作为第n页(在我的情况下作为第10页)附加到Master.pdf。

    生成的PDF应该为新页面添加新的大纲项目(新的书签)。现有的书签也应该保持良好的工作状态。实际上:现有的大纲树应该重构。

    我可以通过iText API实现这一目标吗?有没有有用的样品?

    public class ConcatenateBookmarks {
        public static final String SRC1 = "C:\\c\\spring-in-action.pdf";
        public static final String SRC2 = "C:\\c\\SPD-DUAL DS.pdf";
        public static final String DEST = "C:\\c\\final.pdf";
    
        /**
         * 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 {
            int POINT = 3;
            Document document = new Document();
            PdfSmartCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
            document.open();
            PdfReader reader;
            int page_offset = 0;
            int n;
            // Create a list for the bookmarks
            ArrayList<HashMap<String, Object>> bookmarks = new ArrayList<HashMap<String, Object>>();
            List<HashMap<String, Object>> tmp;
            for (int i = 0; i < 1/* src.length */; i++) {
                reader = new PdfReader(src[i]);
                PdfReader reader2 = new PdfReader(src[1]);
                int pagesCount = reader2.getNumberOfPages();
                page_offset = pagesCount;
                if (i == 0) {
                    HashMap<String, String> map = SimpleNamedDestination.getNamedDestination(reader, false);
                    SimpleNamedDestination.exportToXML(map, new FileOutputStream(dest), "ISO8859-1", false);
                    copy.addNamedDestinations(map, 0);
                }
                tmp = SimpleBookmark.getBookmark(reader);
                // this level have to
                // separate up to n don't
                // change and after the
                // should shift
                SimpleBookmark.shiftPageNumbers(tmp, page_offset,
                   new int[] { POINT, reader.getNumberOfPages() + pagesCount });
                bookmarks.addAll(tmp);
                // add the pages
                n = reader.getNumberOfPages();
                page_offset += n;
                for (int page = 0; page < n;) {
                    copy.addPage(copy.getImportedPage(reader, ++page));
                    if (page == POINT) // add child pages to nth point
                    {
                        for (int page2 = 0; page2 < pagesCount;) {
                            copy.addPage(copy.getImportedPage(reader2, ++page2));
                        }
                    }
                }
                copy.freeReader(reader);
                reader.close();
            }
            // Add the merged bookmarks
            copy.setOutlines(bookmarks);
            // step 5
            document.close();
        }
        /**
         * Main method.
         * 
         * @param args
         *            no arguments needed
         * @throws DocumentException
         * @throws IOException
         * @throws SQLException
         */
        public static void main(String[] args) throws IOException, DocumentException, SQLException {
            new ConcatenateBookmarks().manipulatePdf(new String[] { SRC1, SRC2 }, DEST);
        }
    }
    

1 个答案:

答案 0 :(得分:1)

请查看InsertAndAdaptOutlines示例。我使用PdfStamper代替PdfCopy,但您真正需要的代码是适应PdfOutline的代码。

在我的代码中,我有一个名为bookmarks.pdf的文件:

enter image description here

我插入一个页面&#34; Hello World&#34;所以它是第4页(在你的情况下,更改4到10)导致名为bookmarks_hello.pdf的文件

enter image description here

插入页面是明智的:

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);
...
stamper.close();

最困难的问题是:如何更新大纲树?您可以从PdfReader实例获取大纲树,您可以创建自己的entry想要添加到outlines,然后您可以使用PdfStamper方法将更新的大纲重新放回setOutlines()实例。 (您已经找到了PdfCopyPdfSmartCopy类的类似方法:

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);

我的updateOutline()方法假设现有的大纲树引用了使用GoTo操作的网页:

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);
}

如果您的大纲创建方式不同,您必须调整updateOutline()方法,但此示例应该为您提供足够的灵感来了解它是如何完成的。您必须遍历大纲树中的所有条目,并在适当的位置插入新的entry。然后将新的,已更改的轮廓树放回到生成的PDF中。