使用iText 9.0.0创建PDF大纲指向第一页却跳转至第二页的问题
iText PDF大纲跳转错误修复
问题描述
通过PdfExplicitDestination.createXYZ(pdf.getPage(1), 0, 0, 0)创建指向第一页的"paragraph1"大纲,点击该大纲时却跳转至第二页顶部。
问题原因
在文档内容未完全构建完成时调用pdf.getPage(1),此时页面的实际索引尚未稳定。iText在处理页面添加和分页操作时,页面对象的内部标识可能会在后续内容写入过程中发生变化,导致最初获取的pdf.getPage(1)最终指向了第二页。
解决方案
方法1:延迟创建大纲至内容全部添加完成
将大纲创建逻辑移到所有页面内容添加完毕、文档flush之后,确保页面索引已经确定:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfWriter writer = new PdfWriter(baos); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf, PageSize.A4); // 添加第一页内容 Paragraph paragraph1 = new Paragraph("paragraph1").setDestination("paragraph1"); document.add(paragraph1); // 添加分页和第二页内容 document.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); Paragraph paragraph2 = new Paragraph("paragraph2").setDestination("paragraph2"); document.add(paragraph2); // 内容全部添加完成后再创建大纲 document.flush(); // 创建第一页的大纲,此时pdf.getPage(1)指向正确的第一页 PdfDestination dest = PdfExplicitDestination.createXYZ(pdf.getPage(1), 0, pdf.getPage(1).getMediaBox().getHeight(), 0); PdfOutline coverPageOutline = pdf.getOutlines(true).addOutline("paragraph1 page"); coverPageOutline.addDestination(dest); // 创建第二页的大纲 PdfDestination dest2 = new PdfStringDestination("paragraph2"); PdfOutline outline = pdf.getOutlines(true).addOutline("paragraph2 string"); outline.addDestination(dest2); document.close(); pdf.close();
方法2:使用字符串目标替代直接页面引用
和第二个大纲的实现方式一致,通过设置段落的目标字符串来关联大纲,避免页面索引的问题:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); PdfWriter writer = new PdfWriter(baos); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf, PageSize.A4); Paragraph paragraph1 = new Paragraph("paragraph1").setDestination("paragraph1"); document.add(paragraph1); // 使用字符串目标创建第一页大纲 PdfDestination dest = new PdfStringDestination("paragraph1"); PdfOutline coverPageOutline = pdf.getOutlines(true).addOutline("paragraph1 page"); coverPageOutline.addDestination(dest); document.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); Paragraph paragraph2 = new Paragraph("paragraph2").setDestination("paragraph2"); document.add(paragraph2); dest = new PdfStringDestination("paragraph2"); PdfOutline outline = pdf.getOutlines(true).addOutline("paragraph2 string"); outline.addDestination(dest); document.flush(); document.close(); pdf.close();
说明
方法1通过延迟大纲创建时机,确保页面已经完全初始化,索引准确;方法2利用字符串目标绑定,完全规避页面索引的动态变化问题,两种方式都能解决跳转错误的问题。
内容的提问来源于stack exchange,提问作者王天明
相关产品推荐
相关产品推荐

