需求: 有一个pdf文件source.pdf , 有这个pdf的目录数据Map catalogs , 将catalog作为目录添加到source.pdf文件中 ,且可以点击目录跳转到指定页
描述:原本的source.pdf是没有目录的 , 且catalog目录数据是用别的方法读出来的或者自定义的
工具代码如下:
//需要导入的包
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.draw.DottedLine;
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 com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
public static String createPdfWithCatalog(String sourceFile,
String targetFile,
String catalogTitle,
Map catalogs,
int catalogPageSize) throws IOException {
Map catalogsTemp = new TreeMap<>();
catalogsTemp.putAll(catalogs);
//实际页码索引偏移量为 目录占页数-1
int offset = catalogPageSize - 1;
for (Map.Entry entry : catalogsTemp.entrySet()) {
entry.setValue(entry.getValue() + offset);
}
File file = new File(targetFile);
file.getParentFile().mkdirs();
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(targetFile));
Document document = new Document(pdfDoc);
PdfFont font0 = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
if (catalogTitle == null) {
catalogTitle = " ";
}
document.add(new Paragraph(new Text(catalogTitle))
.setTextAlignment(TextAlignment.CENTER).setFont(font0));
PdfDocument firstSourcePdf = new PdfDocument(new PdfReader(sourceFile));
int numberOfPages = firstSourcePdf.getNumberOfPages();
for (int i = 1; i <= numberOfPages; i++) {
PdfPage page = firstSourcePdf.getPage(i).copyTo(pdfDoc);
pdfDoc.addPage(page);
for (Map.Entry entry : catalogsTemp.entrySet()) {
if (i == entry.getValue()) {
String destinationKey = "p" + (pdfDoc.getNumberOfPages() - 1);
PdfArray destinationArray = new PdfArray();
destinationArray.add(page.getPdfObject());
destinationArray.add(PdfName.XYZ);
destinationArray.add(new PdfNumber(0));
destinationArray.add(new PdfNumber(page.getMediaBox().getHeight()));
destinationArray.add(new PdfNumber(1));
try {
pdfDoc.addNamedDestination(destinationKey, destinationArray);
} catch (Exception e) {
System.out.println(e.getMessage());
}
Paragraph p = new Paragraph();
PdfFont font = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
p.setFont(font);
p.addTabStops(new TabStop(540, TabAlignment.RIGHT, new DottedLine()));
p.add(entry.getKey());
p.add(new Tab());
p.add(String.valueOf(pdfDoc.getNumberOfPages() - 1));
p.setProperty(Property.ACTION, PdfAction.createGoTo(destinationKey));
document.add(p);
}
}
}
firstSourcePdf.close();
document.close();
return targetFile;
}调用示例如下:
Map catalogs = new TreeMap<>();
catalogs.put("Performance by z中文1", 1);
catalogs.put("Performance by z中文12", 2);
catalogs.put("Performance by z中文22", 2);
catalogs.put("Performance by z中文32", 3);
catalogs.put("Performance by z中文42", 4);
catalogs.put("Performance by z中文52", 4);
catalogs.put("Performance by z中文62", 5);
//此处省略N行添加map.....
//catalogPdfPageSize,预测目录会有两页,此参数影响锚点的偏移和目录是否会与主要内容重叠(计算目录页数的方法在文章最后贴出,见分割线)
int catalogPdfPageSize =2;
createPdfWithCatalog("d://源文件.pdf", "d://转换后带有目录的pdf文件.pdf", "目录第一行标题随意啦", catalogs, catalogPdfPageSize);
//
public static int createCatalogPdfOnly(String sourceFile, String targetFile, Map catalogs) throws IOException {
File file = new File(targetFile);
file.getParentFile().mkdirs();
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(targetFile));
Document document = new Document(pdfDoc);
document.add(new Paragraph(new Text("The Revenant nominations list"))
.setTextAlignment(TextAlignment.CENTER));
PdfDocument firstSourcePdf = new PdfDocument(new PdfReader(sourceFile));
for (Map.Entry entry : catalogs.entrySet()) {
Paragraph p = new Paragraph();
p.addTabStops(new TabStop(540, TabAlignment.RIGHT, new DottedLine()));
p.add(entry.getKey());
p.add(new Tab());
p.add(String.valueOf(pdfDoc.getNumberOfPages() - 1));
document.add(p);
}
firstSourcePdf.close();
int pages = pdfDoc.getNumberOfPages();
document.close();
return pages;
}使用示例:
//一个只有一页的pdf文件,必须,该文件必须只有一页!!!
String blankPdf ="d://一个只有一页的pdf文件.pdf";
//生成的只有目录的pdf文件
String catalogPagesTempFile ="随便七个名字把.pdf";
//catalog 即上文中的catalogs数据 ,形式为 Map map ....
int catalogPdfPageSize = createCatalogPdfOnly(blankPdf, catalogPagesTempFile, catalog);
//完成 ,catalogPdfPageSize即目录所占总页数 ,可将此参数用作上边方法得偏移参数