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

来源:互联网 发布:淘宝网服装女装秋装 编辑:程序博客网 时间:2024/06/05 02:37

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




原创粉丝点击