天天看点

PDF带目录导出java_itextpdf为pdf文件添加目录(可跳转)

需求: 有一个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即目录所占总页数 ,可将此参数用作上边方法得偏移参数