How to set the BaseUrl of an existing PDF document?

Tags: actionslink annotationbase URLiText 5

We're having trouble setting a BaseUrl using iTextSharp. We have used Adobes Implementation for this in the past, but we got some severe performance issues. So we switched to iTextSharp, which is aprox 10 times faster.

Adobe enabled us to set a base url for each document. We really need this in order to deploy our documents on different servers. But we cant seem to find the right code to do this.

This code is what we used with Adobe:

public bool SetBaseUrl(object jso, string baseUrl)
{
    try
    {
        object result = jso.GetType().InvokeMember("baseURL", BindingFlags.SetProperty, null, jso, new Object[] {baseUrl });
        return result != null;
    }
    catch
    {
        return false;
    }
}
A lot of solutions describe how you can insert links in new or empty documents. But our documents already exist and do contain more than just text. We want to overlay specific words with a link that leads to one or more other documents. Therefore, its really important to us that we can insert a link without accessing the text itself. Maybe lay a box on top of these words and set its position (since we know where the words are located in the document)

We have tried different implementations, using the setAction method, but it doesn't seem to work properly. The result was in most cases, that we saw out box, but there was no link inside or associated with it. (the cursor didn't change and nothing happened, when I clicked inside the box)

Posted on StackOverflow on Jul 4, 2014 by Chrisi

I've made you a couple of examples.

First, let's take a look at BaseURL1. In your comment, you referred to JavaScript, so I created a document to which I added a snippet of document-level JavaScript:

writer.addJavaScript("this.baseURL = \"http://itextpdf.com/\";");

This works perfectly in Adobe Acrobat, but when you try this in Adobe Reader, you get the following error:

NotAllowedError: Security settings prevent access to this property or method. Doc.baseURL:1:Document-Level:0000000000000000

This is consistent with the JavaScript reference for Acrobat where it is clearly indicated that special permissions are needed to change the base URL.

So instead of following your suggested path, I consulted ISO-32000-1 and I discovered that you can add a URI dictionary to the catalog with a Base entry. So I wrote a second example, BaseURL2, where I add this dictionary to the root dictionary of the PDF:

PdfDictionary uri = new PdfDictionary(PdfName.URI);
uri.put(new PdfName("Base"), new PdfString("http://itextpdf.com/"));
writer.getExtraCatalog().put(PdfName.URI, uri);

Now the BaseURL works in both Acrobat and Reader.

Assuming that you want to add a BaseURL to existing documents, I wrote BaseURL3. In this example, we add the same dictionary to the root dictionary of an existing PDF:

PdfReader reader = new PdfReader(src);
PdfDictionary uri = new PdfDictionary(PdfName.URI);
uri.put(new PdfName("Base"), new PdfString("http://itextpdf.com/"));
reader.getCatalog().put(PdfName.URI, uri);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.close();

Using this code, you can change a link that points to "index.php" (base_url.pdf) into a link that points to "http://itextpdf.com/index.php" (base_url_3.pdf).

Now you can replace your Adobe license with a less expensive iTextSharp license ;-)