itext 7 table 的内容问题
itext 7 table of contents issues
遵循本例中的模式https://kb.itextpdf.com/home/it7kb/examples/toc-as-first-page
我在自己的代码中实现了 table of contents (toc)。一切正常,但有以下例外:
我的目录有 3 页并且可以增长
我可以将pdf的最后两页(toc的2页)移动到顶部
文档,但是当我尝试将目录的第一页移动到
顶部 我得到一个空异常
int tocPageNumber = pdfDoc.GetNumberOfPages();
pdfDoc.MovePage(tocPageNumber, 1);
pdfDoc.MovePage(tocPageNumber, 1);
pdfDoc.MovePage(tocPageNumber, 1); // Null Exception here
doc.Close();
此代码是概念验证。我有逻辑来确定目录中有多少页并将它们循环移动。
屏幕截图:
堆栈跟踪:
at KernelExtensions.Get[TKey,TValue](IDictionary`2 col, TKey key)
at iText.Kernel.Pdf.PdfDictionary.Put(PdfName key, PdfObject value)
at iText.Kernel.Pdf.PdfPages.AddPage(Int32 index, PdfPage pdfPage)
at iText.Kernel.Pdf.PdfPagesTree.AddPage(Int32 index, PdfPage pdfPage)
at iText.Kernel.Pdf.PdfDocument.MovePage(Int32 pageNumber, Int32 insertBefore)
at BlueCoatExtractor.PDFHelper.buildPDFNatively1(String header, String dtStamp, Dictionary`2 bcPoliciesDict, String dest) in C:\Users\xyz\source\repos\bbb\bbb\PDFHelper.cs:line 216
重现问题的完整示例代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using iText.IO.Font.Constants;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Action;
using iText.Kernel.Pdf.Canvas.Draw;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Hyphenation;
using iText.Layout.Layout;
using iText.Layout.Properties;
using iText.Layout.Renderer;
using iText.Kernel.Utils;
namespace BlueCoatExtractor
{
public class C06E04_TOC_GoToNamed
{
public const String SRC = "Logs/jekyll_hyde.txt";
public const String DEST = "Output/jekyll_hyde_toc2.pdf";
internal static void initialize()
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
//new C06E04_TOC_GoToNamed().CreatePdf(DEST);
}
public static void CreatePdf()
{
//Initialize PDF document
PdfDocument pdf = new PdfDocument(new PdfWriter(DEST));
// Initialize document
Document document = new Document(pdf);
PdfFont font = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
PdfFont bold = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
document.SetTextAlignment(TextAlignment.JUSTIFIED).SetHyphenation(new HyphenationConfig("en", "uk", 3, 3))
.SetFont(font).SetFontSize(11);
StreamReader sr = File.OpenText(SRC);
String name;
String line;
Paragraph p;
bool title = true;
int counter = 0;
IList<KeyValuePair<String, KeyValuePair<String, int>>> toc = new List<KeyValuePair
<String, KeyValuePair<String, int>>>();
while ((line = sr.ReadLine()) != null)
{
p = new Paragraph(line);
p.SetKeepTogether(true);
if (title)
{
name = String.Format("title{0:00}", counter++);
KeyValuePair<String, int> titlePage = new KeyValuePair<string, int>(line, pdf.GetNumberOfPages());
p.SetFont(bold).SetFontSize(12).SetKeepWithNext(true).SetDestination(name).SetNextRenderer(new UpdatePageRenderer(p, titlePage));
title = false;
document.Add(p);
toc.Add(new KeyValuePair<string, KeyValuePair<string, int>>(name, titlePage));
}
else
{
p.SetFirstLineIndent(36);
if (String.IsNullOrEmpty(line))
{
p.SetMarginBottom(12);
title = true;
}
else
{
p.SetMarginBottom(0);
}
document.Add(p);
}
}
document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
p = new Paragraph().SetFont(bold).Add("Table of Contents").SetDestination("toc");
document.Add(p);
toc.RemoveAt(0);
IList<TabStop> tabstops = new List<TabStop>();
tabstops.Add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
foreach (KeyValuePair<String, KeyValuePair<String, int>> entry in toc)
{
KeyValuePair<String, int> text = entry.Value;
p = new Paragraph().AddTabStops(tabstops).Add(text.Key).Add(new Tab()).Add(text.Value.ToString()).SetAction
(PdfAction.CreateGoTo(entry.Key));
document.Add(p);
}
//Close document
int tocPageNumber = pdf.GetNumberOfPages();
pdf.MovePage(tocPageNumber, 1);
pdf.MovePage(tocPageNumber, 1);
pdf.MovePage(tocPageNumber, 1); // null exception
document.Close();
}
protected internal class UpdatePageRenderer : ParagraphRenderer
{
protected internal KeyValuePair<String, int> entry;
public UpdatePageRenderer(Paragraph modelElement, KeyValuePair
<String, int> entry)
: base(modelElement)
{
this.entry = entry;
}
public override LayoutResult Layout(LayoutContext layoutContext)
{
LayoutResult result = base.Layout(layoutContext);
int pageNumber = layoutContext.GetArea().GetPageNumber();
entry = new KeyValuePair<string, int>(entry.Key, pageNumber);
return result;
}
}
}
}
使用以下文本文件:https://github.com/itext/i7js-highlevel/blob/develop/src/main/resources/txt/jekyll_hyde.txt
我创建了一个新文档并将原文档的内容复制到其中。 table 内容链接仍按预期运行。
fs = File.Create("Output/resultDoc.pdf");
fs.Dispose();
PdfDocument srcDoc = new PdfDocument(new PdfReader(dest));
var srcTotalPages = srcDoc.GetNumberOfPages();
PdfDocument resultDoc = new PdfDocument(new PdfWriter("Output/resultDoc.pdf"));
resultDoc.InitializeOutlines();
IList<int> pages = new List<int>();
pages.Add(101);
pages.Add(102);
pages.Add(103);
for (int i = 1; i <= 100; i++)
{
pages.Add(i);
}
srcDoc.CopyPagesTo(pages, resultDoc);
resultDoc.Close();
srcDoc.Close();
遵循本例中的模式https://kb.itextpdf.com/home/it7kb/examples/toc-as-first-page 我在自己的代码中实现了 table of contents (toc)。一切正常,但有以下例外:
我的目录有 3 页并且可以增长
我可以将pdf的最后两页(toc的2页)移动到顶部 文档,但是当我尝试将目录的第一页移动到 顶部 我得到一个空异常
int tocPageNumber = pdfDoc.GetNumberOfPages(); pdfDoc.MovePage(tocPageNumber, 1); pdfDoc.MovePage(tocPageNumber, 1); pdfDoc.MovePage(tocPageNumber, 1); // Null Exception here doc.Close();
此代码是概念验证。我有逻辑来确定目录中有多少页并将它们循环移动。
屏幕截图:
堆栈跟踪:
at KernelExtensions.Get[TKey,TValue](IDictionary`2 col, TKey key)
at iText.Kernel.Pdf.PdfDictionary.Put(PdfName key, PdfObject value)
at iText.Kernel.Pdf.PdfPages.AddPage(Int32 index, PdfPage pdfPage)
at iText.Kernel.Pdf.PdfPagesTree.AddPage(Int32 index, PdfPage pdfPage)
at iText.Kernel.Pdf.PdfDocument.MovePage(Int32 pageNumber, Int32 insertBefore)
at BlueCoatExtractor.PDFHelper.buildPDFNatively1(String header, String dtStamp, Dictionary`2 bcPoliciesDict, String dest) in C:\Users\xyz\source\repos\bbb\bbb\PDFHelper.cs:line 216
重现问题的完整示例代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using iText.IO.Font.Constants;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Action;
using iText.Kernel.Pdf.Canvas.Draw;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Hyphenation;
using iText.Layout.Layout;
using iText.Layout.Properties;
using iText.Layout.Renderer;
using iText.Kernel.Utils;
namespace BlueCoatExtractor
{
public class C06E04_TOC_GoToNamed
{
public const String SRC = "Logs/jekyll_hyde.txt";
public const String DEST = "Output/jekyll_hyde_toc2.pdf";
internal static void initialize()
{
FileInfo file = new FileInfo(DEST);
file.Directory.Create();
//new C06E04_TOC_GoToNamed().CreatePdf(DEST);
}
public static void CreatePdf()
{
//Initialize PDF document
PdfDocument pdf = new PdfDocument(new PdfWriter(DEST));
// Initialize document
Document document = new Document(pdf);
PdfFont font = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
PdfFont bold = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
document.SetTextAlignment(TextAlignment.JUSTIFIED).SetHyphenation(new HyphenationConfig("en", "uk", 3, 3))
.SetFont(font).SetFontSize(11);
StreamReader sr = File.OpenText(SRC);
String name;
String line;
Paragraph p;
bool title = true;
int counter = 0;
IList<KeyValuePair<String, KeyValuePair<String, int>>> toc = new List<KeyValuePair
<String, KeyValuePair<String, int>>>();
while ((line = sr.ReadLine()) != null)
{
p = new Paragraph(line);
p.SetKeepTogether(true);
if (title)
{
name = String.Format("title{0:00}", counter++);
KeyValuePair<String, int> titlePage = new KeyValuePair<string, int>(line, pdf.GetNumberOfPages());
p.SetFont(bold).SetFontSize(12).SetKeepWithNext(true).SetDestination(name).SetNextRenderer(new UpdatePageRenderer(p, titlePage));
title = false;
document.Add(p);
toc.Add(new KeyValuePair<string, KeyValuePair<string, int>>(name, titlePage));
}
else
{
p.SetFirstLineIndent(36);
if (String.IsNullOrEmpty(line))
{
p.SetMarginBottom(12);
title = true;
}
else
{
p.SetMarginBottom(0);
}
document.Add(p);
}
}
document.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
p = new Paragraph().SetFont(bold).Add("Table of Contents").SetDestination("toc");
document.Add(p);
toc.RemoveAt(0);
IList<TabStop> tabstops = new List<TabStop>();
tabstops.Add(new TabStop(580, TabAlignment.RIGHT, new DottedLine()));
foreach (KeyValuePair<String, KeyValuePair<String, int>> entry in toc)
{
KeyValuePair<String, int> text = entry.Value;
p = new Paragraph().AddTabStops(tabstops).Add(text.Key).Add(new Tab()).Add(text.Value.ToString()).SetAction
(PdfAction.CreateGoTo(entry.Key));
document.Add(p);
}
//Close document
int tocPageNumber = pdf.GetNumberOfPages();
pdf.MovePage(tocPageNumber, 1);
pdf.MovePage(tocPageNumber, 1);
pdf.MovePage(tocPageNumber, 1); // null exception
document.Close();
}
protected internal class UpdatePageRenderer : ParagraphRenderer
{
protected internal KeyValuePair<String, int> entry;
public UpdatePageRenderer(Paragraph modelElement, KeyValuePair
<String, int> entry)
: base(modelElement)
{
this.entry = entry;
}
public override LayoutResult Layout(LayoutContext layoutContext)
{
LayoutResult result = base.Layout(layoutContext);
int pageNumber = layoutContext.GetArea().GetPageNumber();
entry = new KeyValuePair<string, int>(entry.Key, pageNumber);
return result;
}
}
}
}
使用以下文本文件:https://github.com/itext/i7js-highlevel/blob/develop/src/main/resources/txt/jekyll_hyde.txt
我创建了一个新文档并将原文档的内容复制到其中。 table 内容链接仍按预期运行。
fs = File.Create("Output/resultDoc.pdf");
fs.Dispose();
PdfDocument srcDoc = new PdfDocument(new PdfReader(dest));
var srcTotalPages = srcDoc.GetNumberOfPages();
PdfDocument resultDoc = new PdfDocument(new PdfWriter("Output/resultDoc.pdf"));
resultDoc.InitializeOutlines();
IList<int> pages = new List<int>();
pages.Add(101);
pages.Add(102);
pages.Add(103);
for (int i = 1; i <= 100; i++)
{
pages.Add(i);
}
srcDoc.CopyPagesTo(pages, resultDoc);
resultDoc.Close();
srcDoc.Close();