【发布时间】: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;
}
}
【问题讨论】: