Search code examples
c#pdfitextitext7

How do I modify external link in an existing PDF such that it points to an internal page within document using IText7 and C#?


I have an existing PDF file which has links to external PDF files. I want to edit these links to make them point to pages within the same PDF document. This functionality was working previously with iTextsharp, now I'm migrating to iText7 but can't get it to work.

Below is a sample code that I have tried and feel is very close to the solution but something is missing. This code basically loads up a PDF with 2 pages. The first page has around 15 links all pointing to an external file. I'm trying to edit the links so that they take the user to page 2 of the same document. I am able to load all the links and query their values, but changing them doesn't happen.

    private bool MakeLinksInternal(string inputFile)
    {
      if (Path.GetExtension(inputFile).ToLower() != ".pdf")
        return false;

      using (PdfDocument pdfDocument = new PdfDocument(new PdfReader(inputFile)))
      {
        //get the index page
        PdfPage pdfPage = pdfDocument.GetPage(1);
        //get all of the link annotations for the current page
        var annots = pdfPage.GetAnnotations().Where(a => a.GetSubtype().Equals(PdfName.Link));

        //Make sure we have something
        if ((annots == null) || (annots.Count() == 0))
          return true;

        foreach (PdfLinkAnnotation linkAnnotation in annots)
        {
          //get action associated to the annotation
          var action = linkAnnotation.GetAction();
          if (action == null)
            continue;

          // Test if it is a URI action 
          if (action.Get(PdfName.S).Equals(PdfName.URI)
            || action.Get(PdfName.S).Equals(PdfName.GoToR))
          {
            action.Remove(PdfName.S);

            action.Put(PdfName.S, PdfName.GoTo);

            var newLocalDestination = new PdfArray();
            newLocalDestination.Add(pdfDocument.GetPage(2).GetPdfObject());
            newLocalDestination.Add(PdfName.Fit);

            action.Put(PdfName.D, newLocalDestination);
          }

        }
        pdfDocument.Close();
      }

      return true;
    }

This is my first question in stackoverflow so please be kind if I have made any mistakes in creating this post.


Solution

  • You create the PdfDocument like this

    using (PdfDocument pdfDocument = new PdfDocument(new PdfReader(inputFile)))
    

    This creates a PdfDocument for reading only. If you want to also write the changes you apply, you have to use

    using (PdfDocument pdfDocument = new PdfDocument(new PdfReader(inputFile), new PdfWriter(outputFile)))
    

    You should use different names for inputFile and outputFile.