您的位置:首页 > 编程语言 > PHP开发

itextpdf为pdf文件添加目录(可跳转)

2017-07-21 17:26 525 查看
需求: 有一个pdf文件source.pdf , 有这个pdf的目录数据Map<String,Integer> catalogs , 将catalog作为目录添加到source.pdf文件中 ,且可以点击目录跳转到指定页

描述:原本的source.pdf是没有目录的 , 且catalog目录数据是用别的方法读出来的或者自定义的

原文链接: http://gitlab.itextsupport.com/itext7/samples/blob/master/publications/jumpstart/src/main/java/tutorial/chapter06/C06E06_88th_Oscar_Combine_AddTOC.java
工具代码如下:

//需要导入的包
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;


/**
* 生成一个带有目录(可跳转)的pdf文件(支持中文).
* 如果目录两页,请为pdf多留出一页空白内容.
* 此方法不能生成书签.
*
* @param sourceFile      源pdf文件
* @param targetFile      带有目录(可跳转)的pdf文件
* @param catalogs        目录数据map<标题,页码>
* @param catalogTitle    目录上方第一行文字
* @param catalogPageSize 目录占页大小(为锚点偏移做参数)
* @return targetFile
* @throws IOException
*/
public static String createPdfWithCatalog(String sourceFile,
String targetFile,
String catalogTitle,
Map<String, Integer> catalogs,
int catalogPageSize) throws IOException {
Map<String, Integer> catalogsTemp = new TreeMap<>();
catalogsTemp.putAll(catalogs);
//实际页码索引偏移量为 目录占页数-1
int offset = catalogPageSize - 1;
for (Map.Entry<String, Integer> 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<String, Integer> 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));

b912
document.add(p);
}
}
}
firstSourcePdf.close();
document.close();
return targetFile;
}
调用示例如下:

Map<String, Integer> 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);


///*************一个特别难看的分割线*************************////*一个特别难看的分割线*************************////

计算目录能占多少页的方法,此方法通过用目录数据catalogs生成一个只有目录的pdf,然后返回pdf的page来获取到目录占页数量:

/**
* 新改的方法 ,生成目录pdf ,只是为了方便计算页数.
* 基于createPdfWithCatalog()代码改编,该方法进保留生成目录功能.
*
* @param sourceFile sourceFile
* @param targetFile targetFile
* @param catalogs   catalogs
* @return 目录页数 page size
* @throws IOException IOException
*/
public static int createCatalogPdfOnly(String sourceFile, String targetFile, Map<String, Integer> 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<String, Integer> 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<Strig,Integer> map ....
int catalogPdfPageSize = createCatalogPdfOnly(blankPdf, catalogPagesTempFile, catalog);
//完成 ,catalogPdfPageSize即目录所占总页数 ,可将此参数用作上边方法得偏移参数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: