iTextSharp - PdfSmartCopy - 如何在合并文档中创建内部锚引用?

时间:2014-01-06 19:38:30

标签: merge itextsharp anchor

我正在使用PdfSmartCopy和GetImportedPage合并两个文档。第一个文档包含对第二个文档中锚名称的锚引用。

合并文档时,锚点引用不起作用。这是针对iTextSharp 5.4.5.0

编译的演示代码

在示例代码中,“Go To Anchor 2”在合并文件(file3.pdf)中不起作用。

有没有人解决过这个问题或者能看出原因?

        using (var fs1 = new FileStream("c:/test/file1.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var writer = PdfWriter.GetInstance(doc, fs1);
                doc.Open();
                doc.Add(new Paragraph("Page 1"));
                doc.Add(new Anchor("Go To Anchor 1") { Reference = "#AnchorReference1" });
                doc.Add(new Paragraph(""));
                doc.Add(new Anchor("Go To Anchor 2") { Reference = "#AnchorReference2" });
                doc.NewPage();
                doc.Add(new Paragraph("Page 2"));
                doc.Add(new Anchor("Anchor 1") { Name = "AnchorReference1" });
                doc.Close();
            }
        }

        using (var fs2 = new FileStream("c:/test/file2.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var writer = PdfWriter.GetInstance(doc, fs2);
                doc.Open();
                doc.Add(new Paragraph("Page 3"));
                doc.Add(new Anchor("Anchor 2") { Name = "AnchorReference2" });
                doc.NewPage();
                doc.Close();
            }
        }

        using (var ms3 = new FileStream("c:/test/file3.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var copy = new PdfSmartCopy(doc, ms3);
                doc.Open();
                var pdfReader1 = new PdfReader("c:/test/file1.pdf");
                var pdfReader2 = new PdfReader("c:/test/file2.pdf");
                copy.AddPage(copy.GetImportedPage(pdfReader1, 1));
                copy.AddPage(copy.GetImportedPage(pdfReader1, 2));
                copy.AddPage(copy.GetImportedPage(pdfReader2, 1));
                doc.Close();
            }
        }

以下是同一问题的更新示例,但使用了第二版“iText in action”第7章中ConcatenateNamedDestinations示例中的代码。

        using (var fs1 = new FileStream("c:/test/file1.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var writer = PdfWriter.GetInstance(doc, fs1);
                doc.Open();
                doc.Add(new Paragraph("Page 1"));
                doc.Add(new Anchor("Go To Anchor 1") { Reference = "#AnchorReference1" });
                doc.Add(new Paragraph(""));
                doc.Add(new Anchor("Go To Anchor 2") { Reference = "#AnchorReference2" });
                doc.NewPage();
                doc.Add(new Paragraph("Page 2"));
                doc.Add(new Anchor("Anchor 1") { Name = "AnchorReference1" });
                doc.Close();
            }
        }

        using (var fs2 = new FileStream("c:/test/file2.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var writer = PdfWriter.GetInstance(doc, fs2);
                doc.Open();
                doc.Add(new Paragraph("Page 3"));
                doc.Add(new Anchor("Anchor 2") { Name = "AnchorReference2" });
                doc.NewPage();
                doc.Close();
            }
        }

        PdfReader[] readers = { new PdfReader("c:/test/file1.pdf"), new PdfReader("c:/test/file2.pdf") };

        using (var ms = new FileStream("c:/test/file3.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var document = new  Document())
            {
                using (var copy = new PdfCopy(document, ms))
                {
                    document.Open();
                    int n;
                    for (int i = 0; i < readers.Length; i++)
                    {
                        readers[i].ConsolidateNamedDestinations();
                        n = readers[i].NumberOfPages;
                        for (int page = 0; page < n; )
                        {
                            copy.AddPage(copy.GetImportedPage(readers[i], ++page));
                        }
                    }
                    // Add named destination  
                    copy.AddNamedDestinations(
                        // from the second document
                      SimpleNamedDestination.GetNamedDestination(readers[1], false),
                        // using the page count of the first document as offset
                      readers[0].NumberOfPages
                    );
                }
            }

            // Create a reader
            var reader = new PdfReader("c:/test/file3.pdf");
            // Convert the remote destinations into local destinations
            reader.MakeRemoteNamedDestinationsLocal();
            using (var ms2 = new FileStream("c:/test/file4.pdf", FileMode.Create, FileAccess.Write))
            {
                // Create a new PDF containing the local destinations
                using (var stamper = new PdfStamper(reader, ms2))
                {
                }
            }
        }

解决:

        using (var fs1 = new FileStream("c:/test/file1.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var writer = PdfWriter.GetInstance(doc, fs1);
                doc.Open();
                doc.Add(new Paragraph("Page 1"));
                var anchor1Chunk = new Chunk("Click for Anchor 1");
                var anchor2Chunk = new Chunk("Click for Anchor 2");
                anchor1Chunk.SetAction(PdfAction.GotoLocalPage("AnchorReference1", false));
                anchor2Chunk.SetAction(PdfAction.GotoLocalPage("AnchorReference2", false));
                doc.Add(new Paragraph(anchor1Chunk));
                doc.Add(new Paragraph(anchor2Chunk));
                doc.NewPage();
                doc.Add(new Paragraph("Page 2"));
                doc.Add(new Anchor("Anchor 1") { Name = "AnchorReference1" });
                doc.Close();
            }
        }

        using (var fs2 = new FileStream("c:/test/file2.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var doc = new iTextSharp.text.Document())
            {
                var writer = PdfWriter.GetInstance(doc, fs2);
                doc.Open();
                doc.Add(new Paragraph("Page 3"));
                doc.Add(new Anchor("Anchor 2") { Name = "AnchorReference2" });
                doc.NewPage();
                doc.Close();
            }
        }

        PdfReader[] readers = { new PdfReader("c:/test/file1.pdf"), new PdfReader("c:/test/file2.pdf") };

        using (var ms = new FileStream("c:/test/file3.pdf", FileMode.Create, FileAccess.Write))
        {
            using (var document = new  Document())
            {
                using (var copy = new PdfCopy(document, ms))
                {
                    document.Open();
                    int n;
                    for (int i = 0; i < readers.Length; i++)
                    {
                        readers[i].ConsolidateNamedDestinations();
                        n = readers[i].NumberOfPages;
                        for (int page = 0; page < n; )
                        {
                            copy.AddPage(copy.GetImportedPage(readers[i], ++page));
                        }
                    }
                    // Add named destination  
                    copy.AddNamedDestinations(
                        // from the second document
                      SimpleNamedDestination.GetNamedDestination(readers[1], false),
                        // using the page count of the first document as offset
                      readers[0].NumberOfPages
                    );
                }
            }
        }

1 个答案:

答案 0 :(得分:1)

如果使用命名目的地从文档A到文档B有链接,并且如果将文档A与文档B合并得到文档C,则显然文档A中的链接仍然引用文档B ,而不是文件C.

如果您希望它们引用文档C,您需要合并命名目标并使远程链接本地化,如本书第7章中所述。请参阅ConcatenateNamedDestinations示例:Java version / C# version