Search code examples
pythonpdfrelative-pathpypdffile-uri

How to add a relative file path inside a pdf using pypdf


Context

  1. I have a pdf with links.
  2. I want to replace all the external links with local files in the same folder.
  3. Is there a way to do that in pypdf or python

e.g.

outputStream = open("destination.pdf", "wb")
key = '/Annots'
uri = '/URI'
ank = '/A'
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
cwd = os.getcwd()
for x in range(existing_pdf.getNumPages()):
    page = existing_pdf.getPage(x)
    page_object = page.getObject()

    if key in page_object:
        ann = page_object[key]
        for a in ann:
            u = a.getObject()
            if uri in u[ank]:
                test = u[ank][uri]
                test1 = u[ank].keys()
                u[TextStringObject(ank)][TextStringObject(uri)] = TextStringObject(f"file:./foo1.pdf")
    output.addPage(page)
    # finally, write "output" to a real file
    output.write(outputStream)
outputStream.close()

The above does not work i.e. the foo1.pdf is not linked properly. If I add "file:///{CWD}/foo1.pdf" it works. Is there a way to use relative path only?


Solution

  • After reading through the pdf structure and documentation I was able to write the following and it works as expected.

       for x in range(existing_pdf.getNumPages()):
        page = existing_pdf.getPage(x)
        page_object = page.getObject()
        if key in page_object:
            ann = page_object[key]
            for a in ann:
                u = a.getObject()
                if uri in u[ank]:
                    del u[TextStringObject(ank)][TextStringObject(uri)]
                    u[TextStringObject(ank)][NameObject('/F')] = TextStringObject(f"./sheets/sheet1.pdf")
                    u[TextStringObject(ank)][TextStringObject('/S')] = NameObject("/Launch")
                    u[TextStringObject(ank)][NameObject('/NewWindow')] = BooleanObject(f"true")
        output.addPage(page)
        # finally, write "output" to a real file
        output.write(outputStream)
    outputStream.close()