Retrieving Revision of a PDF Document
Signing appends rather than rewrites, so a document signed twice contains three
versions of itself: the original and 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
prevReader, err := reader.GetRevision(0)
if err != nil {
return err
}
appender, err := model.NewPdfAppender(prevReader)
if err != nil {
return err
}
return appender.WriteToFile(outputPath)Revision 0 is the document before any incremental update, so on a twice-signed file it
has no signatures at all. GetRevision(reader.GetRevisionNumber()) returns the same
reader you passed in, not a copy.
Writing the revision out through an appender that has nothing appended reproduces the
revision’s bytes as a standalone document. 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 signs the input twice to manufacture the revisions, then calls
retrieveSpecificRevision with revision 0 to write the unsigned original back out.
retrievePreviousRevision, which is what you want when you only care about the state
before the last change, is in the source with the call commented out in main.
git clone https://github.com/unidoc/unipdf-examples.git
cd unipdf-examples/signatures
go run pdf_sign_get_revision.go <IN.pdf> <OUT.pdf>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
PDF file successfully signed
PDF file successfully signed
PDF file successfully signed. Output path: signed_and_get_revision.pdf
Done