pdf合并、生成目录大纲

效果图

合并a.pdf和b.pdf两个文件,会自动提取待合并的pdf原有的大纲。
在这里插入图片描述

aspose.pdf 合并pdf (不推荐、非常耗内存)

/**
     * 合并pdf,可以根据别名生成pdf的书签
     *
     * @param fileRefers
     * @param targetPath
     */
    public static void mergePdfUseRelative(List<ZipUtil.RelativeFile> fileRefers, String targetPath) {
        long startTime = System.currentTimeMillis();
        if (FileUtils.newFile(targetPath).exists()) {
            FileUtils.newFile(targetPath).delete();
        }

        com.aspose.pdf.Document resultPdf = new Document();
        resultPdf.save(targetPath);

        Document mergedDocument = new com.aspose.pdf.Document(targetPath);
        // 设置文档信息
        DocumentInfo docInfo = new DocumentInfo(mergedDocument);
        docInfo.setAuthor("匿名");
        docInfo.setKeywords("文件");
        docInfo.setProducer("ueh");

        int totalPage = 0;
        int index = 0;

        PageCollection mergedDocumentPages = mergedDocument.getPages();

        for (ZipUtil.RelativeFile sourcePdf : fileRefers) {
            log.info("开始合并{}, 大小:{}MB, 路径:{}", (++index),
                    FileUtils.newFile(sourcePdf.getFilePath()).length() / 1024 / 1024,
                    sourcePdf.getFilePath());
            long time1 = System.currentTimeMillis();


            Document pdf = new com.aspose.pdf.Document(sourcePdf.getFilePath());
            PageCollection pdfPages = pdf.getPages();
            mergedDocumentPages.add(pdfPages);

            // 每个待合并文件一个一级目录。
            // 书签保存在Document对象的OutlineItemCollection集合中,而它本身在OutlineCollection 集合中。
            // Create a bookmark object
            OutlineItemCollection pdfOutline = new OutlineItemCollection(mergedDocument.getOutlines());
            pdfOutline.setTitle(FileUtils.newFile(sourcePdf.getRelativePath()).getName());
            pdfOutline.setItalic(true);
            pdfOutline.setBold(true);
            // Set the destination page number
            pdfOutline.setAction(new GoToAction(mergedDocumentPages.get_Item(1 + totalPage)));

            // 添加一级目录的子目录(每个文件自己的目录)
            // Create PdfBookmarkEditor
            PdfBookmarkEditor bookmarkEditor = new PdfBookmarkEditor();
            // Open PDF file
            bookmarkEditor.bindPdf(sourcePdf.getFilePath());
            // Extract bookmarks 读取一级目录
            Bookmarks bookmarks = bookmarkEditor.extractBookmarks(true);
            // 添加书签
            addBookmark(mergedDocument, mergedDocumentPages, pdfOutline, totalPage, bookmarks);

            // Add bookmark in the document's outline collection.
            mergedDocument.getOutlines().add(pdfOutline);

            // 更新总页码
            totalPage += pdfPages.size();

            // 保存
            mergedDocument.save();
            log.info("结束合并,当前合并{}页,总{}页:{},耗费:{}秒", pdfPages.size(), mergedDocumentPages.size(),
                    sourcePdf.getFilePath(), (System.currentTimeMillis() - time1) / 1000);

            pdfPages.clear();
            pdf.close();
        }
        mergedDocument.close();

        log.info("合并完成:共耗时{}秒", (System.currentTimeMillis() - startTime) / 1000);
    }

    /**
     * 给指定的父亲目录添加子目录
     *
     * @param mergedDocument 合并后的最终文档
     * @param pdfOutline     每个pdf的目录。一级目录。
     * @param totalPage      合并 当前后的总页码
     * @param bookmarks      每个待合并的小pdf的一级书签
     */
    public static void addBookmark(Document mergedDocument, PageCollection mergedDocumentPages,
                                   OutlineItemCollection pdfOutline, int totalPage, Bookmarks bookmarks) {
        // 这里是把所有的书签都读取出来了。
        for (int i = 0; i < bookmarks.size(); i++) {
            Bookmark b = bookmarks.get_Item(i);

            //  添加一级目录的子目录
            OutlineItemCollection pdfChildOutline = new OutlineItemCollection(mergedDocument.getOutlines());
            pdfChildOutline.setTitle(b.getTitle());
            pdfChildOutline.setItalic(true);
            pdfChildOutline.setBold(true);
            pdfChildOutline.setAction(new GoToAction(mergedDocumentPages.get_Item(b.getPageNumber() + totalPage)));
            // Add child bookmark in parent bookmark's collection
            pdfOutline.add(pdfChildOutline);

            // 有子级书签
            Bookmarks childItems = b.getChildItems();
            if (childItems.size() > 0) {
                addBookmark(mergedDocument, mergedDocumentPages, pdfChildOutline, totalPage, childItems);
            }

        }
    }

pdfbox (推荐,内存耗费较小,合并快)

    /**
     * 合并Pdf文件
     *
     * @param files        需要合并的文件路径
     * @param destFilePath
     */
    public static void mergePdf(List<String> files, String destFilePath) {
        log.info("开始合并{}, 大小:{}MB, 路径:{}", 0, 0, 0);
        long time1 = System.currentTimeMillis();

        // pdf合并工具类
        PDFMergerUtility mergePdf = new PDFMergerUtility();

        // 自定义书签对象
        List<PdfBoxBookmark> allBookList = new ArrayList<>();
        int totalPage = 0;
        int index = 0;

        // 添加待合并文件
        for (String item : files) {
            log.info("开始添加{}, 大小:{}MB, 路径:{}", (++index),
                    FileUtils.newFile(item).length() / 1024 / 1024, item);
            // 读取Document 方式2
//            FileInputStream fis = new FileInputStream(FileUtils.newFile(item))
//            PDFParser parser = new PDFParser(new RandomAccessBuffer(fis));
//            parser.parse();
//            PDDocument doc = parser.getPDDocument();

            try (PDDocument document = PDDocument.load(FileUtils.newFile(item), MemoryUsageSetting.setupTempFileOnly());
            ) {
                // 页面大纲(1级)
                PdfBoxBookmark boxData = new PdfBoxBookmark(FileUtils.newFile(item).getName(), totalPage, null);

                PDDocumentOutline outline = document.getDocumentCatalog().getDocumentOutline();
                if (outline != null) {
                    buildBookMark(outline, boxData, totalPage);
                }
                /
                allBookList.add(boxData);

                mergePdf.addSource(item);

                // 更新总页码
                totalPage += document.getNumberOfPages();
            } catch (IOException e) {
                throw new BaseException("文件不存在:" + item);
            }
            log.info("结束添加,添加后,总{}页:{},耗费:{}秒",totalPage,
                    item, (System.currentTimeMillis() - time1) / 1000);
        }

        // 设置合并后的pdf文件路径
        mergePdf.setDestinationFileName(destFilePath);

        // 合并pdf
        try {
            mergePdf.setDocumentMergeMode(PDFMergerUtility.DocumentMergeMode.OPTIMIZE_RESOURCES_MODE);
            mergePdf.mergeDocuments(MemoryUsageSetting.setupTempFileOnly());
        } catch (IOException e) {
            throw new BaseException("合并发生异常");
        }

        // 添加书签
        try (PDDocument mergedDocument = PDDocument.load(FileUtils.newFile(destFilePath),
                MemoryUsageSetting.setupTempFileOnly())) {
            // 给合并后的文档设置文档大纲(1级目录)
            PDDocumentOutline documentOutline = new PDDocumentOutline();
            mergedDocument.getDocumentCatalog().setDocumentOutline(documentOutline);

            addBookmark(mergedDocument, allBookList, documentOutline, null);

            mergedDocument.save(destFilePath);
        } catch (IOException e) {
            throw new BaseException("文件不存在:");
        }

        log.info("结束合并,当前合并{}页,总{}页:{},耗费:{}秒", 0, 0,
                0, (System.currentTimeMillis() - time1) / 1000);
    }

    /**
     * 添加书签
     * @param mergedDocument 合并后的文档对象
     * @param allBookList 自定义的书签树
     * @param documentOutline
     * @param pagesOutline 调用时候传递null
     */
    public static void addBookmark(PDDocument mergedDocument, List<PdfBoxBookmark> allBookList,
                                       PDDocumentOutline documentOutline, PDOutlineItem pagesOutline) {
        for (PdfBoxBookmark boxData : allBookList) {
            // 给每个文档构造 页面大纲(一级书签)
            PDPageDestination pageDestination = new PDPageFitWidthDestination();
            pageDestination.setPage(mergedDocument.getPage(boxData.getPage()));
            PDOutlineItem bookmark = new PDOutlineItem();
            bookmark.setDestination(pageDestination);
            bookmark.setTitle(boxData.getTitle());

            // 需要给每个页面大纲添加子目录 PDOutlineItem
            List<PdfBoxBookmark> children = boxData.getChildren();
            if (children != null && children.size() > 0) {
                addBookmark(mergedDocument, children, documentOutline, bookmark);
            }

            if (pagesOutline == null) {
                // 给文档大纲 添加 页面大纲
                documentOutline.addLast(bookmark);
            } else {
                pagesOutline.addLast(bookmark);
            }

        }
    }

    /**
     * 构建自定义书签
     * @param bookmark
     * @param boxData
     * @param totalPage
     * @throws IOException
     */
    public static void buildBookMark(PDOutlineNode bookmark, PdfBoxBookmark boxData, int totalPage) throws IOException {
        PDOutlineItem current = bookmark.getFirstChild();
        while (current != null) {
            int pages = 0;
            PDDestination destination = current.getDestination();
            if (destination instanceof PDPageDestination) {
                PDPageDestination pd = (PDPageDestination) destination;
                pages = pd.retrievePageNumber() + totalPage;
            }
            if (boxData.getChildren() == null) {
                boxData.setChildren(new ArrayList<>());
            }

            List<PdfBoxBookmark> children = boxData.getChildren();
            PdfBoxBookmark tmpBox = new PdfBoxBookmark(current.getTitle(), pages, null);
            children.add(tmpBox);
            // 这里需要判断是否有儿子。有儿子用tmpBox, 没有儿子用boxData
            if (current.hasChildren()) {
                buildBookMark(current, tmpBox, totalPage);
            } else {
                buildBookMark(current, boxData, totalPage);
            }

            boxData.setChildren(children);
            current = current.getNextSibling();
        }
    }


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: WPS Office是一款功能强大的办公软件,其中包含了WPS Writer文档编辑器和WPS PDF转换器。 WPSPDF自动生成目录功能可以很方便地为PDF文档生成目录。操作步骤如下: 首先,将需要生成目录的文档转换为PDF格式。可以在WPS Writer中打开文档,然后点击菜单栏中的"文件",选择"转换为PDF",将文档保存为PDF格式。 接着,在WPS PDF转换器中打开刚才保存的PDF文件。点击工具栏中的"目录"按钮,系统将自动扫描文档内容,并根据章节标题、子标题等信息生成目录生成目录列表将显示在PDF文档的侧边栏中,用户可以根据需要将其打开或关闭。 如果文档中有标题或内容发生变化,可以重新点击"目录"按钮进行更新。系统将重新扫描文档并生成新的目录。 此外,用户还可以自定义目录样式。点击工具栏中的"目录选项"按钮,可以设置目录的字体、字号、颜色等属性。 需要注意的是,要正确生成目录,文档中的章节标题、子标题等必须使用WPS Writer的相关样式进行标记。例如,将章节标题设置为"标题1"样式,子标题设置为"标题2"样式。 总之,WPSPDF自动生成目录功能使得对于含有复杂章节结构的文档,用户可以很方便地生成目录列表,提升文档的可读性和导航性。这一功能的使用也非常简单,只需几步操作即可完成目录生成。 ### 回答2: WPS PDF是一款功能强大的PDF编辑器,其中自动生成目录功能让用户能够轻松地为文档添加目录。 首先,打开WPS PDF并加载你想要自动生成目录PDF文档。在左侧的“工具”栏中,你会看到一个名为“大纲”的选项。点击它,你将看到一个弹出窗口。 接下来,你需要标记出你想要在目录中显示的部分标题。在文档中选择第一个标题并在“大纲”窗口中点击“添加”。这将添加第一级标题。 如果文档中有更多级别的标题,你可以在“大纲”窗口中选择相应级别,然后选择相应标题并点击“添加”。通过这种方式,你可以为文档中的多个标题添加目录级别。 完成所有标题的标记后,点击“生成目录”按钮。WPS PDF将根据你在“大纲”窗口中添加的标题自动创建目录。你可以选择将目录插入到当前页面或者作为整个文档的最后一页。 生成目录后,你可以对其进行进一步的调整和编辑。你可以添加页码,格式化目录的样式以及调整标题的层次结构。通过使用WPS PDF的其他编辑功能,你还可以为目录添加书签、链接等。 最后,保存你的文档,并在需要时打印或分享。现在,你已经成功地使用WPS PDF自动生成了一个含有目录PDF文档。 总之,WPS PDF的自动生成目录功能为用户提供了一个简便而强大的工具,使他们能够快速创建具有标准格式的目录,提高文档的可读性和导航性。 ### 回答3: WPS PDF是一款功能强大的PDF编辑工具,它不仅可以编辑和转换PDF文件,还有自动生成目录的功能。 在使用WPS PDF自动生成目录功能的时候,首先我们需要打开需要编辑的PDF文件。然后,点击软件界面上方的“导航”选项卡,接着点击“目录”按钮。 在弹出的目录管理窗口中,我们可以选择自动生成目录的样式。WPS PDF提供了多种不同的样式可供选择,包括带数字标签、带点标签、不带标签等。我们可以根据自己的需求选择相应的样式。 接下来,我们需要选择生成目录的范围。WPS PDF支持生成整个文档的目录,也支持根据文档的标题级别生成目录。如果我们只想生成某几个章节的目录,可以选择相应的章节进行生成。 在确定样式和范围后,我们点击“确定”按钮即可生成目录。WPS PDF会根据文档的标题级别自动生成目录,并将其插入到文档的指定位置。 生成目录后,我们可以对目录进行进一步的编辑。例如,可以修改目录的字体、样式和标题级别等。只需要选中目录,然后点击界面上方的“样式”选项卡,进行相应的编辑即可。 总之,WPS PDF提供了便捷的自动生成目录功能,可以帮助我们更好地组织和管理PDF文件的内容。无论是编辑大型报告还是整理学习资料,WPS PDF都能提供高效的工具和功能,让我们的工作更加便捷和高效。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值