【问题标题】:Multiple Table of content pages when merging PDF-files using iTextPDF使用 iTextPDF 合并 PDF 文件时的多个目录页
【发布时间】:2021-03-04 13:18:53
【问题描述】:

我正在尝试合并多个 PDF 文件并创建要添加到合并的 pdf 文件的目录。我正在使用 java 和 iTextPDF。当文件列表长于一定数量的文件时,该页面的目录运行并且它不会创建第二个目录页面。我修改了代码以添加新页面,但出于某种原因,它会覆盖之前的目录页面。结果是 1 页的目录,但包含指向最后文件的链接。如何保留所有目录页?如果我有 50 个文件,我需要包含所有 50 个页面链接的多个目录页面。

import com.itextpdf.forms.PdfPageFormCopier;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfOutline;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.ReaderProperties;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.canvas.draw.DashedLine;
import com.itextpdf.kernel.pdf.navigation.PdfDestination;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Tab;
import com.itextpdf.layout.element.TabStop;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.property.TabAlignment;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    public static final String DEST = "/MergeFolder/merge_with_toc.pdf";
    public static final String TEMPLATE = "/MergeFolder/TOC.pdf";
    public static final String FILEPATH = "/MergeFolder/Input/";



    public static void main(String[] args) throws IOException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();

        new Main().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(baos));
        Document doc = new Document(pdfDoc);

        // Copier contains the additional logic to copy acroform fields to a new page.
        // PdfPageFormCopier uses some caching logic which can potentially improve performance
        // in case of the reusing of the same instance.
        PdfPageFormCopier formCopier = new PdfPageFormCopier();

        // Get files
        File folder = new File(FILEPATH);
        File[] listOfFiles = folder.listFiles();

        // Copy all merging file's pages to the temporary pdf file
        Map<String, PdfDocument> filesToMerge = initializeFilesToMerge(listOfFiles);
        Map<Integer, String> toc = new TreeMap<Integer, String>();
        int page = 1;
        for (Map.Entry<String, PdfDocument> entry : filesToMerge.entrySet()) {
            PdfDocument srcDoc = entry.getValue();
            int numberOfPages = srcDoc.getNumberOfPages();

            toc.put(page, entry.getKey());

            for (int i = 1; i <= numberOfPages; i++, page++) {
                Text text = new Text(String.format("Page %d", page));
                srcDoc.copyPagesTo(i, i, pdfDoc, formCopier);

                // Put the destination at the very first page of each merged document
                if (i == 1) {
                    text.setDestination("p" + page);

                    PdfOutline rootOutLine = pdfDoc.getOutlines(false);
                    PdfOutline outline = rootOutLine.addOutline("p" + page);
                    outline.addDestination(PdfDestination.makeDestination(new PdfString("p" + page)));
                }

                doc.add(new Paragraph(text)
                        .setFixedPosition(page, 549, 810, 40)
                        .setMargin(0)
                        .setMultipliedLeading(1));
            }
        }

        PdfDocument tocDoc = new PdfDocument(new PdfReader(TEMPLATE));
        tocDoc.copyPagesTo(1, 1, pdfDoc, formCopier);
        tocDoc.close();

        // Create a table of contents
        float tocYCoordinate = 750;
        float tocXCoordinate = doc.getLeftMargin();
        float tocWidth = pdfDoc.getDefaultPageSize().getWidth() - doc.getLeftMargin() - doc.getRightMargin();
        int k = 0;
        for (Map.Entry<Integer, String> entry : toc.entrySet()) {
            k = k+1;
            Paragraph p = new Paragraph();
            p.addTabStops(new TabStop(500, TabAlignment.LEFT, new DashedLine()));
            p.add(entry.getValue());
            p.add(new Tab());
            p.add(String.valueOf(entry.getKey()));
            p.setAction(PdfAction.createGoTo("p" + entry.getKey()));
            doc.add(p
                    .setFixedPosition(pdfDoc.getNumberOfPages(), tocXCoordinate, tocYCoordinate, tocWidth)
                    .setMargin(0)
                    .setMultipliedLeading(1));

            tocYCoordinate -= 20;

            if (k>25){
                k = 1;
                tocDoc = new PdfDocument(new PdfReader(TEMPLATE));
                tocDoc.copyPagesTo(1, 1, pdfDoc, formCopier);
                tocDoc.close();
                tocYCoordinate = 750;
            }
        }

        for (PdfDocument srcDoc : filesToMerge.values()) {
            srcDoc.close();
        }

        doc.close();

        PdfDocument resultDoc = new PdfDocument(new PdfWriter(dest));
        PdfDocument srcDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(baos.toByteArray()),
                new ReaderProperties()));
        srcDoc.initializeOutlines();

        // Create a copy order list and set the page with a table of contents as the first page
        int tocPageNumber = srcDoc.getNumberOfPages();
        List<Integer> copyPagesOrderList = new ArrayList<>();
        copyPagesOrderList.add(tocPageNumber);
        for(int i = 1; i < tocPageNumber; i++) {
            copyPagesOrderList.add(i);
        }

        srcDoc.copyPagesTo(copyPagesOrderList, resultDoc, formCopier);

        srcDoc.close();
        resultDoc.close();
    }

    private static Map<String, PdfDocument> initializeFilesToMerge(File[] _listOfFiles) throws IOException {
        Map<String, PdfDocument> filesToMerge = new TreeMap<String, PdfDocument>();

        for (File file : _listOfFiles) {
            if (file.isFile()) {
                if(file.getName().indexOf(".") != 0) {

                    String fileName = file.getName();
                    String filePath = file.getAbsolutePath();

                    filesToMerge.put(fileName, new PdfDocument(new PdfReader(filePath)));
                }
            }
        }

        return filesToMerge;
    }
}

【问题讨论】:

    标签: java pdf itext


    【解决方案1】:

    我不确定您是否仍然遇到此问题。我将我的目录加载到一个列表中,这样我就可以获得子项目。这是在 C# 中,因此您必须修改语法。我有一些 4 页的 TOC,没有问题,

    public static int CreateTableOfContentsFromOutline(PdfMerger merger, PdfDocument sourceDocument)
        {
            MemoryStream memoryStream = new MemoryStream();
            PdfDocument pdfDocument = new PdfDocument(new PdfWriter(memoryStream));
            Document document = new Document(pdfDocument);
    
            PdfFont font = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
            PdfFont bold = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
    
            List tableOfContents = new List();
    
            ProcessOutlineChildren(pdfDocument, tableOfContents, sourceDocument.GetOutlines(false).GetAllChildren());
    
            document.Add(new Paragraph("Table of Contents")
                .SetFontSize(18)
                .SetFont(bold)
                .SetTextAlignment(TextAlignment.CENTER)
                .SetDestination("toc"));
    
            document.Add(tableOfContents);
    
            int pagecount = pdfDocument.GetNumberOfPages();
    
    
            pdfDocument.Close();
            document.Close();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-01
      • 2023-03-12
      相关资源
      最近更新 更多