PdfDocumentRewriter class
Full rewrite of a PDF, with garbage collection.
Saving a loaded document produces an incremental update: the original bytes are copied whole and the change goes at the end. That preserves signatures, but nothing is ever removed from the file — old revisions, objects nobody references any more and deleted content stay there, readable by any tool that walks the bytes.
The rewrite does the opposite: it builds a new PdfDocument and imports into it the graph reachable from the catalog of the source. Whatever is not reachable simply is not written. There is no "erase" step: there is a step that copies what matters, and the rest is left behind.
final saneado = await PdfDocumentRewriter.rewrite(bytes);
// With a report:
final result = await PdfDocumentRewriter().rewriteBytes(bytes);
print(result.report); // objetos 443 -> 257, bytes 2589459 -> 566480
Rewriting breaks every existing signature
A digital signature covers the exact bytes of the document it was applied
to, declared in the /ByteRange. The rewrite renumbers objects,
recompresses streams and rebuilds the xref: none of those bytes survive,
and no digest checks out again. There is no rewrite that preserves a
signature.
This is not a side effect to work around — it is the reason the rewrite serves as the basis for sanitizing. As long as the file keeps the old signature, it keeps along with it the revision that signature covered, and it is exactly in that revision that the content one wanted to remove lives. That is why PdfRewriteOptions.keepInvalidSignatures exists for forensics and history, never for validation, and why safe redaction (phase 9 of the roadmap) requires a rewrite.
The default behavior is that of SEI and of most tools on the market: it rewrites, turns the signature widget into a read-only stamp and warns. PdfRewriteOptions.rejectSignedSources refuses instead of warning.
What this phase still does NOT do
- It is not redaction. Removing text or an image from inside a content stream is still the business of phases 8 and 9 of the roadmap. The rewrite copies the content streams as they are: whatever was drawn on the page stays drawn, including under a black rectangle. What it guarantees is that no earlier revision with the content is left — not that the content of the current revision is gone.
- It does not decrypt. A document with
/Encryptis refused with a PdfMergeException; there is no reading security handler. - It does not preserve the
/ID. The new file gets a new identifier, which is correct for a document whose bytes changed entirely, but breaks any external link that depended on the old identifier. - It does not rewrite the structural tagging. With PdfRewriteOptions.keepStructureTree the tree is copied as it is; it is not rebuilt from the content.
- It does not use object streams in the output. A very compact source file can grow; the gain comes from dropping revisions, not from recompressing.
- It does not renumber under the caller's control. The output numbering is the import order; there is no option to preserve the source numbers.
Constructors
- PdfDocumentRewriter({PdfRewriteOptions? options, bool compress = true, PdfVersion version = PdfVersion.pdf_1_5, DeflateCallback? deflate, bool verbose = false})
- Creates a reusable rewriter.
Properties
- compress → bool
-
Compresses the generated streams.
final
- deflate → DeflateCallback?
-
Alternative compressor;
zlib.encodeondart:io.final - hashCode → int
-
The hash code for this object.
no setterinherited
- options → PdfRewriteOptions
-
What to preserve.
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- verbose → bool
-
Emits the serialization trace.
final
- version → PdfVersion
-
Version declared in the output file.
final
Methods
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
rewriteBytes(
Uint8List bytes, {bool useIsolate = false}) → Future< PdfRewriteResult> - Rewrites the bytes of a PDF.
-
rewriteDocument(
PdfDocumentParser source, {int? bytesBefore, bool useIsolate = false}) → Future< PdfRewriteResult> - Rewrites a document already opened by a parser.
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Methods
-
rewrite(
Uint8List bytes, {PdfRewriteOptions? options, bool compress = true, PdfVersion version = PdfVersion.pdf_1_5, DeflateCallback? deflate, bool useIsolate = false}) → Future< Uint8List> -
Rewrites
bytesand returns only the new file.