Retrieving Revision of a PDF Document
Signing appends rather than rewrites, so a document signed twice contains every
version it had before plus one revision per signature. A PdfReader can hand
you a reader over any of them, which is how you recover what a signature actually
signed rather than what the file looks like now.
| Call | Returns |
|---|---|
GetRevisionNumber() | The revision the reader is currently on. The original file is 0. |
GetPreviousRevision() | A reader one revision back. |
GetRevision(n) | A reader on revision n, walking back from the current one. |
Getting a revision
// Before signing.
inputRevision := pdfReader.GetRevisionNumber()
// ... sign twice, reopen the result as reader ...
prevReader, err := reader.GetRevision(inputRevision)
if err != nil {
return err
}
appender, err := model.NewPdfAppender(prevReader)
if err != nil {
return err
}
return appender.WriteToFile(outputPath)Recording GetRevisionNumber before signing is what makes this work for any input.
Revision 0 is the document before any incremental update, which is the unsigned
original only when the input had never been updated. An input that already carries a
signature, or any other incremental update, has a higher number, and asking for 0
would discard those revisions too. GetRevision(reader.GetRevisionNumber()) returns
the same reader you passed in, not a copy.
Writing the revision out through an appender that has nothing appended keeps the
revision’s bytes unchanged at the start of the file and adds a small update after
them with a new /Info dictionary and catalog. A PdfWriter obtained from
prevReader.ToWriter would work too, but it rebuilds the file and so does not preserve
the byte ranges any signature in that revision depends on.
Limitations
Revision numbers are absolute, not relative. GetRevision rejects anything outside
0..GetRevisionNumber() with wrong revision number, and GetPreviousRevision on the
original returns previous version is not exist.
Revisions are only visible where the document was built by incremental update. A file that was signed, then rewritten by another tool, is one revision as far as the parser is concerned, whatever its history.
Each revision is a full PdfReader over the truncated byte range, and they are cached
on the reader, so walking back through a heavily updated document holds every
intermediate revision in memory until the reader is released.
GetRevision walks backwards one revision at a time, so asking for revision 0 of a
document with fifty revisions parses fifty of them.
Run the example
The example records the input’s revision number, signs the input twice with
generated keys, then calls retrieveSpecificRevision with the recorded number to
write the document as it was before signing. For an input with no incremental updates
that is revision 0; for an input that was already signed once it is revision 1.
retrievePreviousRevision, which writes the state before the last change (here, the
document with only the first new signature), is in the source with the call commented
out in main.
git clone https://github.com/unidoc/unipdf-examples.git
cd unipdf-examples/signatures/signing
go run pdf_sign_get_revision.go <INPUT_PDF_PATH> <OUTPUT_PDF_PATH>If this is your first time using UniPDF, follow the getting started guide to create an API key and set up your development environment.
View the full source
Sample output
2026/10/21 13:08:52 PDF file successfully signed
2026/10/21 13:08:52 PDF file successfully signed
2026/10/21 13:08:52 Revision 0 written to output path: signed_and_get_revision.pdf
Done