Incremental update is a method to modify a PDF document without affecting its original content. It simply appends the changes at the end of the file that not only saves the time required to re-write the entire document but also minimizes the risk of data loss. This feature is especially important while updating the digitally signed PDF documents as it allows to add new signature to a document without invalidating the original signature.
DsPdf allows you to incrementally update and save a modified document using Save method. By default, this method saves the document without an incremental update. However, you can save the document incrementally by setting the incrementalUpdate parameter of the Save method to true. The Save method provides two more overloads which take SaveMode enumeration as a parameter. The SaveMode enumeration gives you option to save the PDF documents in default mode, linearized mode or incremental update mode. To save a document with incremental updates, you can also set the SaveMode enumeration to IncrementalUpdate while passing it as a parameter to the Save method. Note that incremental updates can not be included in a linearized document. That is, linearized and incremental update modes are mutually exclusive modes. For more information regarding linearized mode, see Linearization.
Additionally, DsPdf provides Sign method to sign and save a document which by default updates the document incrementally. Alternatively, you can also set the SaveMode enumeration to IncrementalUpdate and pass it as a parameter to Sign method. Both these methods let you sign a document multiple times without invalidating the original signature and without changing its original content. DsPdf allows three levels of subsequent changes on a signed document:
Note that once a document has been signed, adding a new field invalidates the existing signature. Hence, a document must already have enough signature fields to accommodate all the subsequent signatures. Also, if you run a sample that uses a signed PDF without a valid license key of DsPdf, then the original signature in the generated PDF is invalidated. This happens because a license header is added to the PDF in such cases which changes the original signed document.
To incrementally update a PDF file:
C# |
Copy Code
|
---|---|
static void Main(string[] args) { // Load an existing PDF using FileStream FileStream fileStream = File.OpenRead(args[0].ToString()); GcPdfDocument doc = new GcPdfDocument(); doc.Load(fileStream); const float In = 72; var tf = new TextFormat() { Font = StandardFonts.CourierItalic, FontSize = 12 }; doc.Pages[0].Graphics.DrawString ("This is a sample text for incremental update", tf, new PointF(In, In)); doc.Save("IncUpdate", true); // Alternatively, use the below overload. // doc.Save("IncUpdate", SaveMode.IncrementalUpdate); } |
To add multiple digital signatures in a PDF document:
C# |
Copy Code
|
---|---|
public class SignIncremental { public void CreatePDF(Stream stream) { GcPdfDocument doc = new GcPdfDocument(); // Load a signed document (we use code similar to the SignDoc sample): doc.Load(CreateAndSignPdf()); // Init a second certificate: var pfxPath = Path.Combine("Resources", "Misc", "JohnDoe.pfx"); X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(pfxPath), "secret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); SignatureProperties sp2 = new SignatureProperties() { Certificate = cert, Location = "DsPdfWeb Sample Browser", SignerName = "John Doe", }; // Find the 2nd (not yet filled) signature field: var sfld2 = doc.AcroForm.Fields["SecondSignature"] as SignatureField; // Connect the signature field and signature props: sp2.SignatureField = sfld2 ?? throw new Exception ("Unexpected: could not find 'SecondSignature' field"); // Sign and save the document: // NOTES: // - Signing and saving is an atomic operation, the two cannot be separated. // - The stream passed to the Sign() method must be readable. doc.Sign(sp2, stream); // Rewind the stream to read the document just created // into another GcPdfDocument and verify all signatures: stream.Seek(0, SeekOrigin.Begin); GcPdfDocument doc2 = new GcPdfDocument(); doc2.Load(stream); foreach (var fld in doc2.AcroForm.Fields) if (fld is SignatureField sfld) if (!sfld.Value.VerifySignature()) throw new Exception($"Failed to verify signature for field {sfld.Name}"); // Done (the generated and signed docment has already been saved to 'stream'). } // This method is almost exactly the same as the DigitalSignature sample, // but adds a second signature field (does not sign it though): private Stream CreateAndSignPdf() { GcPdfDocument doc = new GcPdfDocument(); Page page = doc.NewPage(); TextFormat tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 }; page.Graphics.DrawString( "Hello, World!\r\nSigned below TWICE by DsPdfWeb SignIncremental sample" + ".\r\n(Note that some browser built-in viewers may not show the signatures.)", tf, new PointF(72, 72)); // Init a test certificate: var pfxPath = Path.Combine("Resources", "Misc", "DsPdfTest.pfx"); X509Certificate2 cert = new X509Certificate2(File.ReadAllBytes(pfxPath), "qq", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); SignatureProperties sp = new SignatureProperties(); sp.Certificate = cert; sp.Location = "DsPdfWeb Sample Browser"; sp.SignerName = "DsPdfWeb"; // Init a signature field to hold the signature: SignatureField sf = new SignatureField(); sf.Widget.Rect = new RectangleF(72, 72 * 2, 72 * 4, 36); sf.Widget.Page = page; sf.Widget.BackColor = Color.LightSeaGreen; sf.Widget.TextFormat.Font = StandardFonts.Helvetica; sf.Widget.ButtonAppearance.Caption = $"Signer: {sp.SignerName}"+ "\r\nLocation: {sp.Location}"; // Add the signature field to the document: doc.AcroForm.Fields.Add(sf); // Connect the signature field and signature props: sp.SignatureField = sf; // Add a second signature field: SignatureField sf2 = new SignatureField() { Name = "SecondSignature" }; sf2.Widget.Rect = new RectangleF(72, 72 * 3, 72 * 4, 36); sf2.Widget.Page = page; sf2.Widget.BackColor = Color.LightYellow; // Add the signature field to the document: doc.AcroForm.Fields.Add(sf2); var ms = new MemoryStream(); doc.Sign(sp, ms); return ms; } |
For more information about how to make incremental updates in a PDF document using DsPdf, see DsPdf sample browser.