diff --git a/facades-annotations/add-annotation-verbose-logging.cs b/facades-annotations/add-annotation-verbose-logging.cs new file mode 100644 index 00000000..ea883f33 --- /dev/null +++ b/facades-annotations/add-annotation-verbose-logging.cs @@ -0,0 +1,68 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class Program +{ + public static void Main(string[] args) + { + string inputPath = null; + string outputPath = null; + bool verbose = false; + + foreach (string arg in args) + { + if (arg.Equals("--verbose", StringComparison.OrdinalIgnoreCase)) + { + verbose = true; + } + else if (inputPath == null) + { + inputPath = arg; + } + else if (outputPath == null) + { + outputPath = arg; + } + } + + if (string.IsNullOrEmpty(inputPath) || string.IsNullOrEmpty(outputPath)) + { + Console.Error.WriteLine("Usage: program.exe [--verbose]"); + return; + } + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + if (verbose) + { + doc.EnableNotificationLogging = true; + } + + Page page = doc.Pages[1]; + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 500, 300, 550); + TextAnnotation annotation = new TextAnnotation(page, rect); + annotation.Title = "Verbose Example"; + annotation.Contents = "Annotation added with verbose logging."; + page.Annotations.Add(annotation); + + doc.Save(outputPath); + } + + Console.WriteLine($"PDF saved to '{outputPath}'."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/agents.md b/facades-annotations/agents.md new file mode 100644 index 00000000..b68c009a --- /dev/null +++ b/facades-annotations/agents.md @@ -0,0 +1,175 @@ +--- +name: Facades - Annotations +description: C# examples for Facades - Annotations using Aspose.PDF for .NET +language: csharp +framework: net10.0 +parent: ../agents.md +--- + +# AGENTS - Facades - Annotations + +## Persona + +You are a C# developer specializing in PDF processing using Aspose.PDF for .NET, +working within the **Facades - Annotations** category. +This folder contains standalone C# examples for Facades - Annotations operations. +See the root [agents.md](../agents.md) for repository-wide conventions and boundaries. + +## Scope +- This folder contains examples for **Facades - Annotations**. +- Files are standalone `.cs` examples stored directly in this folder. + +## Files in this folder +- [add-annotation-verbose-logging](./add-annotation-verbose-logging.cs) +- [annotation-count-per-page](./annotation-count-per-page.cs) +- [annotation-performance-logger](./annotation-performance-logger.cs) +- [annotation-summary-report](./annotation-summary-report.cs) +- [async-delete-annotations](./async-delete-annotations.cs) +- [backup-before-flattening](./backup-before-flattening.cs) +- [batch-annotation-flattening-cancel](./batch-annotation-flattening-cancel.cs) +- [batch-delete-annotations-progress](./batch-delete-annotations-progress.cs) +- [batch-delete-annotations-report](./batch-delete-annotations-report.cs) +- [batch-delete-annotations-retain](./batch-delete-annotations-retain.cs) +- [batch-delete-stamp-annotations](./batch-delete-stamp-annotations.cs) +- [batch-import-xfdf-annotations](./batch-import-xfdf-annotations.cs) +- [batch-process-azure-pdf](./batch-process-azure-pdf.cs) +- [batch-update-annotation-author](./batch-update-annotation-author.cs) +- [benchmark-delete-annotations](./benchmark-delete-annotations.cs) +- [check-duplicate-annotation-names](./check-duplicate-annotation-names.cs) +- [clone-annotation-change-color](./clone-annotation-change-color.cs) +- [clone-modify-annotation](./clone-modify-annotation.cs) +- [compare-annotation-counts](./compare-annotation-counts.cs) +- [concurrent-import-delete](./concurrent-import-delete.cs) +- [copy-annotations-template-to-multiple](./copy-annotations-template-to-multiple.cs) +- [count-pdf-annotation-types](./count-pdf-annotation-types.cs) +- [delete-all-annotations](./delete-all-annotations.cs) +- [delete-annotation-by-name](./delete-annotation-by-name.cs) +- [delete-annotation-by-name__v2](./delete-annotation-by-name__v2.cs) +- [delete-annotation-error-handling](./delete-annotation-error-handling.cs) +- [delete-annotations-by-author](./delete-annotations-by-author.cs) +- [delete-annotations-by-color](./delete-annotations-by-color.cs) +- [delete-annotations-by-name](./delete-annotations-by-name.cs) +- [delete-annotations-export-xfdf](./delete-annotations-export-xfdf.cs) +- [delete-annotations-folder](./delete-annotations-folder.cs) +- [delete-annotations-from-config](./delete-annotations-from-config.cs) +- [delete-annotations-parallel](./delete-annotations-parallel.cs) +- [delete-annotations-unit-test](./delete-annotations-unit-test.cs) +- [delete-annotations-with-backup](./delete-annotations-with-backup.cs) +- [delete-annotations-with-logging](./delete-annotations-with-logging.cs) +- [delete-flatten-annotations](./delete-flatten-annotations.cs) +- [delete-pdf-annotation-retry](./delete-pdf-annotation-retry.cs) +- [delete-pdf-annotations](./delete-pdf-annotations.cs) +- [delete-text-annotations](./delete-text-annotations.cs) +- [diagnostic-annotation-workflow](./diagnostic-annotation-workflow.cs) +- [export-annotations-empty-pdf](./export-annotations-empty-pdf.cs) +- [export-annotations-pretty-xfdf](./export-annotations-pretty-xfdf.cs) +- [export-annotations-unbound-test](./export-annotations-unbound-test.cs) +- [export-annotations-xfdf-custom-namespace](./export-annotations-xfdf-custom-namespace.cs) +- [export-annotations-xfdf-gzip](./export-annotations-xfdf-gzip.cs) +- [export-annotations-xfdf-log](./export-annotations-xfdf-log.cs) +- [export-annotations-xfdf](./export-annotations-xfdf.cs) +- [export-delete-archive-annotations](./export-delete-archive-annotations.cs) +- [export-highlight-annotations](./export-highlight-annotations.cs) +- [export-import-annotations-xfdf](./export-import-annotations-xfdf.cs) +- [export-pdf-annotations-json](./export-pdf-annotations-json.cs) +- [export-pdf-annotations-xfdf](./export-pdf-annotations-xfdf.cs) +- [export-pdf-annotations-xfdf__v2](./export-pdf-annotations-xfdf__v2.cs) +- [extract-annotation-authors](./extract-annotation-authors.cs) +- [extract-annotation-details](./extract-annotation-details.cs) +- [extract-annotation-rectangles](./extract-annotation-rectangles.cs) +- [extract-annotation-summary](./extract-annotation-summary.cs) +- [flatten-annotations-first-five-pages](./flatten-annotations-first-five-pages.cs) +- [flatten-annotations-log-sizes](./flatten-annotations-log-sizes.cs) +- [flatten-annotations-verify](./flatten-annotations-verify.cs) +- [flatten-pdf-add-metadata](./flatten-pdf-add-metadata.cs) +- [flatten-pdf-annotations-nightly](./flatten-pdf-annotations-nightly.cs) +- [flatten-pdf-annotations](./flatten-pdf-annotations.cs) +- [flatten-pdf-annotations__v2](./flatten-pdf-annotations__v2.cs) +- [flatten-pdf-annotations__v3](./flatten-pdf-annotations__v3.cs) +- [flatten-pdf-annotations__v4](./flatten-pdf-annotations__v4.cs) +- [flatten-pdf-custom-output](./flatten-pdf-custom-output.cs) +- [folder-monitor-flatten-pdf-annotations](./folder-monitor-flatten-pdf-annotations.cs) +- [get-annotation-names-by-author](./get-annotation-names-by-author.cs) +- [import-annotations-no-overwrite](./import-annotations-no-overwrite.cs) +- [import-annotations-xfdf](./import-annotations-xfdf.cs) +- [import-xfdf-and-cleanup](./import-xfdf-and-cleanup.cs) +- [import-xfdf-annotations](./import-xfdf-annotations.cs) +- [import-xfdf-annotations__v2](./import-xfdf-annotations__v2.cs) +- [import-xfdf-into-multiple-pdfs](./import-xfdf-into-multiple-pdfs.cs) +- [list-annotation-names](./list-annotation-names.cs) +- [list-annotations-csv](./list-annotations-csv.cs) +- [log-annotation-modification](./log-annotation-modification.cs) +- [measure-flatten-annotations](./measure-flatten-annotations.cs) +- [merge-annotations](./merge-annotations.cs) +- [merge-xfdf-files](./merge-xfdf-files.cs) +- [modify-annotation-author](./modify-annotation-author.cs) +- [modify-annotation-flags](./modify-annotation-flags.cs) +- [modify-annotation-subject-color](./modify-annotation-subject-color.cs) +- [modifyannotations-subject-test](./modifyannotations-subject-test.cs) +- [pdf-annotation-helper](./pdf-annotation-helper.cs) +- [pdf-utility-cli](./pdf-utility-cli.cs) +- [pdfannotation-editor-wrapper](./pdfannotation-editor-wrapper.cs) +- [pdfannotationeditor-health-check](./pdfannotationeditor-health-check.cs) +- [preserve-annotation-appearance](./preserve-annotation-appearance.cs) +- [remove-all-annotations](./remove-all-annotations.cs) +- [remove-link-annotations](./remove-link-annotations.cs) +- [remove-old-annotations](./remove-old-annotations.cs) +- [remove-pdf-annotations](./remove-pdf-annotations.cs) +- [rename-annotation-names](./rename-annotation-names.cs) +- [retry-annotation-modification](./retry-annotation-modification.cs) +- [safeguard-flattening-signatures](./safeguard-flattening-signatures.cs) +- [set-annotations-open](./set-annotations-open.cs) +- [set-readonly-annotation](./set-readonly-annotation.cs) +- [skip-flatten-readonly-annotations](./skip-flatten-readonly-annotations.cs) +- [update-annotation-modified-date](./update-annotation-modified-date.cs) +- [validate-no-annotations-after-flattening](./validate-no-annotations-after-flattening.cs) +- [validate-pdf-integrity](./validate-pdf-integrity.cs) +- [validate-xfdf](./validate-xfdf.cs) + +## Category Statistics +- Total examples: 105 + +## Category-Specific Tips + +### Key API Surface +- `Aspose.Pdf.Annotations.AnnotationType` +- `Aspose.Pdf.Facades.AutoFiller` +- `Aspose.Pdf.Facades.AutoFiller.BindPdf` +- `Aspose.Pdf.Facades.AutoFiller.Close` +- `Aspose.Pdf.Facades.AutoFiller.Dispose` +- `Aspose.Pdf.Facades.AutoFiller.ImportDataTable` +- `Aspose.Pdf.Facades.AutoFiller.InputFileName` +- `Aspose.Pdf.Facades.AutoFiller.InputStream` +- `Aspose.Pdf.Facades.AutoFiller.OutputStream` +- `Aspose.Pdf.Facades.AutoFiller.OutputStreams` +- `Aspose.Pdf.Facades.AutoFiller.Save` +- `Aspose.Pdf.Facades.AutoFiller.UnFlattenFields` +- `Aspose.Pdf.Facades.BDCProperties` +- `Aspose.Pdf.Facades.BDCProperties.E` +- `Aspose.Pdf.Facades.BDCProperties.Lang` + +### Rules +- Instantiate Aspose.Pdf.Facades.PdfContentEditor, bind the source PDF via BindPdf({input_pdf}), then call CreateFileAttachment({rect}, {string_literal}, {string_literal}, {int}, {string_literal}, {float}) where the parameters are the annotation rectangle, description, attached file path, page number, icon name, and icon transparency. +- After adding the annotation, persist the changes by invoking Save({output_pdf}) on the same PdfContentEditor instance. +- To delete all annotations: instantiate {class:PdfAnnotationEditor}, call BindPdf({input_pdf}), invoke DeleteAnnotations(), then Save({output_pdf}). +- PdfAnnotationEditor must be bound to a PDF via BindPdf before any annotation‑related methods (e.g., DeleteAnnotations) can be used. +- Bind a PDF file ({input_pdf}) to a PdfAnnotationEditor instance using BindPdf before any annotation operations. + +### Warnings +- The example uses System.Drawing.Rectangle for the annotation bounds, which requires a reference to System.Drawing.Common on non‑Windows platforms. +- Transparency support may depend on the chosen icon and PDF viewer. +- The example does not use a using statement for FileStream; callers should ensure proper disposal. +- Only FreeText and Line annotation types are shown; other types can be included by adding their string names to the array. +- AutoFiller is in the Facades namespace — add 'using Aspose.Pdf.Facades;' explicitly. + +## General Tips +- See parent [agents.md](../agents.md) for: + - **Boundaries** — Always / Ask First / Never rules for all examples + - **Common Mistakes** — verified anti-patterns that cause build failures + - **Domain Knowledge** — cross-cutting API-specific gotchas + - **Testing Guide** — build and run verification steps +- Review code examples in this folder for Facades - Annotations patterns + + +Updated: 2026-03-27 | Run: `20260327_002039_d7a850` + diff --git a/facades-annotations/annotation-count-per-page.cs b/facades-annotations/annotation-count-per-page.cs new file mode 100644 index 00000000..991e1067 --- /dev/null +++ b/facades-annotations/annotation-count-per-page.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + int pageCount = doc.Pages.Count; + Console.WriteLine($"Document has {pageCount} page(s)."); + + for (int i = 1; i <= pageCount; i++) + { + Page page = doc.Pages[i]; + int annotationCount = page.Annotations.Count; + Console.WriteLine($"Page {i}: {annotationCount} annotation(s)"); + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/annotation-performance-logger.cs b/facades-annotations/annotation-performance-logger.cs new file mode 100644 index 00000000..6206a246 --- /dev/null +++ b/facades-annotations/annotation-performance-logger.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using System.Diagnostics; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class AnnotationPerformanceLogger +{ + public static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + // Iterate through all pages (1‑based indexing) + for (int i = 1; i <= doc.Pages.Count; i++) + { + Page page = doc.Pages[i]; + + // ----- Add a TextAnnotation and measure duration ----- + Stopwatch addTimer = Stopwatch.StartNew(); + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 500, 300, 550); + TextAnnotation textAnn = new TextAnnotation(page, rect); + textAnn.Title = "Note"; + textAnn.Contents = $"Added on page {i}"; + textAnn.Color = Aspose.Pdf.Color.Yellow; + page.Annotations.Add(textAnn); + addTimer.Stop(); + Console.WriteLine($"Add TextAnnotation on page {i} took {addTimer.ElapsedMilliseconds} ms"); + + // ----- Delete the just‑added annotation and measure duration ----- + Stopwatch deleteTimer = Stopwatch.StartNew(); + // Annotations collection uses 1‑based indexing as well + page.Annotations.Delete(page.Annotations.Count); + deleteTimer.Stop(); + Console.WriteLine($"Delete last annotation on page {i} took {deleteTimer.ElapsedMilliseconds} ms"); + } + + doc.Save(outputPath); + } + + Console.WriteLine($"Processed PDF saved as '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/annotation-summary-report.cs b/facades-annotations/annotation-summary-report.cs new file mode 100644 index 00000000..cbc6ea5c --- /dev/null +++ b/facades-annotations/annotation-summary-report.cs @@ -0,0 +1,69 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main(string[] args) + { + if (args == null || args.Length == 0) + { + Console.WriteLine("Usage: AnnotationSummaryReport [ ...]"); + return; + } + + foreach (string pdfPath in args) + { + if (!File.Exists(pdfPath)) + { + Console.Error.WriteLine($"File not found: {pdfPath}"); + continue; + } + + ProcessPdf(pdfPath); + } + } + + private static void ProcessPdf(string pdfPath) + { + using (Document doc = new Document(pdfPath)) + { + Dictionary counts = new Dictionary(); + + for (int i = 1; i <= doc.Pages.Count; i++) + { + Page page = doc.Pages[i]; + AnnotationCollection annotations = page.Annotations; + + for (int j = 1; j <= annotations.Count; j++) + { + Annotation ann = annotations[j]; + AnnotationType type = ann.AnnotationType; + if (counts.ContainsKey(type)) + { + counts[type] = counts[type] + 1; + } + else + { + counts.Add(type, 1); + } + } + } + + Console.WriteLine($"File: {Path.GetFileName(pdfPath)}"); + if (counts.Count == 0) + { + Console.WriteLine(" No annotations found."); + } + else + { + foreach (KeyValuePair kvp in counts) + { + Console.WriteLine($" {kvp.Key}: {kvp.Value}"); + } + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/async-delete-annotations.cs b/facades-annotations/async-delete-annotations.cs new file mode 100644 index 00000000..6e137123 --- /dev/null +++ b/facades-annotations/async-delete-annotations.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static async Task Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor(doc)) + { + // Perform the annotation operation asynchronously to avoid blocking the UI thread. + await Task.Run(() => editor.DeleteAnnotations()); + + // Save the modified document. + doc.Save(outputPath); + } + } + + Console.WriteLine($"Annotations processed asynchronously and saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/backup-before-flattening.cs b/facades-annotations/backup-before-flattening.cs new file mode 100644 index 00000000..83ca2247 --- /dev/null +++ b/facades-annotations/backup-before-flattening.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string backupPath = "backup.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Load the original PDF + using (Document document = new Document(inputPath)) + { + // Create a backup copy before any flattening operation + document.Save(backupPath); + + // Perform flattening (removes form fields and annotations) + // Aspose.Pdf provides a parameter‑less Flatten method; advanced options are not required for basic flattening. + document.Flatten(); + + // Save the flattened result + document.Save(outputPath); + } + + Console.WriteLine($"Backup created at '{backupPath}' and flattened PDF saved as '{outputPath}'."); + } +} diff --git a/facades-annotations/batch-annotation-flattening-cancel.cs b/facades-annotations/batch-annotation-flattening-cancel.cs new file mode 100644 index 00000000..6eb4cdd6 --- /dev/null +++ b/facades-annotations/batch-annotation-flattening-cancel.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Multithreading; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Create an interrupt monitor which provides a cancellation token. + using (InterruptMonitor interruptMonitor = new InterruptMonitor()) + { + // Link the monitor's token to a CancellationTokenSource for Task cancellation. + CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(interruptMonitor.CancellationToken); + + // Run the flattening operation on a background task. + Task flattenTask = Task.Run(() => + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.FlatteningAnnotations(); + editor.Save(outputPath); + } + }, linkedCts.Token); + + Console.WriteLine("Press 'C' to cancel the flattening operation..."); + while (!flattenTask.IsCompleted) + { + if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.C) + { + // Request interruption – the monitor will signal cancellation. + interruptMonitor.Interrupt(); + break; + } + Thread.Sleep(100); + } + + try + { + flattenTask.Wait(); + if (!flattenTask.IsCanceled) + { + Console.WriteLine($"Flattening completed. Output saved to '{outputPath}'."); + } + } + catch (AggregateException aggEx) + { + if (aggEx.InnerException is OperationCanceledException) + { + Console.WriteLine("Flattening operation was cancelled by the user."); + } + else + { + Console.Error.WriteLine($"Error during flattening: {aggEx.InnerException?.Message}"); + } + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/batch-delete-annotations-progress.cs b/facades-annotations/batch-delete-annotations-progress.cs new file mode 100644 index 00000000..69ed072b --- /dev/null +++ b/facades-annotations/batch-delete-annotations-progress.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputFolder = "input"; + const string outputFolder = "output"; + + // Ensure both input and output directories exist + Directory.CreateDirectory(inputFolder); + Directory.CreateDirectory(outputFolder); + + // Get all PDF files in the input folder + string[] pdfFiles = Directory.GetFiles(inputFolder, "*.pdf"); + int totalFiles = pdfFiles.Length; + + if (totalFiles == 0) + { + Console.WriteLine($"No PDF files found in the '{inputFolder}' folder."); + return; + } + + const int progressBarWidth = 50; // characters + + for (int i = 0; i < totalFiles; i++) + { + string inputPath = pdfFiles[i]; + string outputPath = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(inputPath) + "_clean.pdf"); + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.DeleteAnnotations(); + editor.Save(outputPath); + } + + // ----- Progress reporting ----- + int percent = (i + 1) * 100 / totalFiles; + int filledLength = percent * progressBarWidth / 100; + string bar = new string('█', filledLength) + new string('─', progressBarWidth - filledLength); + Console.Write($"\rProcessing {i + 1}/{totalFiles} [{bar}] {percent}%"); + } + + // Move to the next line after the loop finishes + Console.WriteLine(); + Console.WriteLine("Batch annotation deletion completed."); + } +} diff --git a/facades-annotations/batch-delete-annotations-report.cs b/facades-annotations/batch-delete-annotations-report.cs new file mode 100644 index 00000000..514475b4 --- /dev/null +++ b/facades-annotations/batch-delete-annotations-report.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + // Folder containing the PDF files to process + string inputFolder = "input_pdfs"; + if (!Directory.Exists(inputFolder)) + { + Console.Error.WriteLine($"Folder not found: {inputFolder}"); + return; + } + + string[] pdfFiles = Directory.GetFiles(inputFolder, "*.pdf"); + if (pdfFiles.Length == 0) + { + Console.WriteLine("No PDF files found in the specified folder."); + return; + } + + foreach (string pdfPath in pdfFiles) + { + // Load the PDF document + using (Document doc = new Document(pdfPath)) + { + int totalAnnotations = 0; + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + totalAnnotations += doc.Pages[pageIndex].Annotations.Count; + } + + // Prepare output file name (simple filename, no directory) + string outputFileName = Path.GetFileNameWithoutExtension(pdfPath) + "_clean.pdf"; + + // Delete all annotations using PdfAnnotationEditor + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(pdfPath); + editor.DeleteAnnotations(); + editor.Save(outputFileName); + } + + Console.WriteLine($"{Path.GetFileName(pdfPath)}: {totalAnnotations} annotations removed, saved as {outputFileName}"); + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/batch-delete-annotations-retain.cs b/facades-annotations/batch-delete-annotations-retain.cs new file mode 100644 index 00000000..9ec23dde --- /dev/null +++ b/facades-annotations/batch-delete-annotations-retain.cs @@ -0,0 +1,88 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text.Json; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string configPath = "retain-config.json"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + if (!File.Exists(configPath)) + { + Console.Error.WriteLine($"Config file not found: {configPath}"); + return; + } + + // Load configuration JSON that lists annotation types to retain + string json = File.ReadAllText(configPath); + RetainConfig config = JsonSerializer.Deserialize(json); + if (config == null || config.Retain == null) + { + Console.Error.WriteLine("Invalid configuration file."); + return; + } + + // Build a case‑insensitive set for fast lookup + HashSet retainSet = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (string type in config.Retain) + { + retainSet.Add(type); + } + + // Open PDF with PdfAnnotationEditor + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + + Document doc = editor.Document; // underlying document + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + AnnotationCollection annColl = page.Annotations; + + // Collect indices of annotations that are NOT in the retain list + List indicesToDelete = new List(); + for (int i = 1; i <= annColl.Count; i++) + { + Annotation ann = annColl[i]; + string annType = ann.GetType().Name; // e.g., TextAnnotation, HighlightAnnotation + if (annType.EndsWith("Annotation", StringComparison.Ordinal)) + { + annType = annType.Substring(0, annType.Length - "Annotation".Length); + } + if (!retainSet.Contains(annType)) + { + indicesToDelete.Add(i); + } + } + + // Delete from highest index to lowest to keep collection indices valid + for (int i = indicesToDelete.Count - 1; i >= 0; i--) + { + annColl.Delete(indicesToDelete[i]); + } + } + + editor.Save(outputPath); + } + + Console.WriteLine($"Annotations retained according to config. Saved to '{outputPath}'."); + } + + private class RetainConfig + { + public List Retain { get; set; } + } +} \ No newline at end of file diff --git a/facades-annotations/batch-delete-stamp-annotations.cs b/facades-annotations/batch-delete-stamp-annotations.cs new file mode 100644 index 00000000..3876847c --- /dev/null +++ b/facades-annotations/batch-delete-stamp-annotations.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputDirectory = "pdfs"; + if (!Directory.Exists(inputDirectory)) + { + Console.Error.WriteLine($"Directory not found: {inputDirectory}"); + return; + } + + string[] pdfFiles = Directory.GetFiles(inputDirectory, "*.pdf"); + foreach (string pdfPath in pdfFiles) + { + string fileName = Path.GetFileName(pdfPath); + string outputFile = "cleaned_" + fileName; + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(pdfPath); + editor.DeleteAnnotations("Stamp"); + editor.Save(outputFile); + Console.WriteLine($"Processed '{fileName}' -> '{outputFile}'"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/batch-import-xfdf-annotations.cs b/facades-annotations/batch-import-xfdf-annotations.cs new file mode 100644 index 00000000..eb12cab9 --- /dev/null +++ b/facades-annotations/batch-import-xfdf-annotations.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + // Directory containing PDFs and matching XFDF files (current directory) + string[] pdfFiles = Directory.GetFiles(".", "*.pdf"); + + foreach (string pdfPath in pdfFiles) + { + string baseName = Path.GetFileNameWithoutExtension(pdfPath); + string xfdfPath = baseName + ".xfdf"; + + if (File.Exists(xfdfPath)) + { + try + { + using (Document pdfDoc = new Document(pdfPath)) + { + // Import annotations from the matching XFDF file + pdfDoc.ImportAnnotationsFromXfdf(xfdfPath); + + // Save the annotated PDF with a new simple filename + string outputFileName = baseName + "_annotated.pdf"; + pdfDoc.Save(outputFileName); + Console.WriteLine($"Processed '{pdfPath}' with '{xfdfPath}' -> '{outputFileName}'"); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error processing '{pdfPath}': {ex.Message}"); + } + } + else + { + Console.WriteLine($"No matching XFDF for '{pdfPath}', skipping."); + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/batch-process-azure-pdf.cs b/facades-annotations/batch-process-azure-pdf.cs new file mode 100644 index 00000000..b1b83208 --- /dev/null +++ b/facades-annotations/batch-process-azure-pdf.cs @@ -0,0 +1,120 @@ +// Program.cs +using System; +using System.IO; +using System.Collections.Generic; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string connectionString = "UseDevelopmentStorage=true"; // placeholder – not used by stub + const string containerName = "pdf-container"; + + // Initialise the (stub) Blob service and container + BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); + BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName); + containerClient.CreateIfNotExists(); + + // Iterate over all blobs (PDF files) in the container + foreach (BlobItem blobItem in containerClient.GetBlobs()) + { + string blobName = blobItem.Name; + BlobClient blobClient = containerClient.GetBlobClient(blobName); + + // Download the blob into a memory stream + using (MemoryStream inputStream = new MemoryStream()) + { + blobClient.DownloadTo(inputStream); + inputStream.Position = 0; + + // Edit annotations using Aspose.Pdf.Facades.PdfAnnotationEditor + using (PdfAnnotationEditor annotationEditor = new PdfAnnotationEditor()) + { + annotationEditor.BindPdf(inputStream); + using (MemoryStream outputStream = new MemoryStream()) + { + annotationEditor.Save(outputStream); + outputStream.Position = 0; + + // Upload the processed PDF back to the same blob (overwrite) + blobClient.Upload(outputStream, overwrite: true); + } + } + } + Console.WriteLine($"Processed blob: {blobName}"); + } + } +} + +// --------------------------------------------------------------------------- +// Azure.Storage.Blobs stub implementation (for compilation without the real SDK) +// --------------------------------------------------------------------------- +namespace Azure.Storage.Blobs +{ + using System.Collections.Generic; + using System.IO; + using Azure.Storage.Blobs.Models; + + public class BlobServiceClient + { + private readonly string _connectionString; + public BlobServiceClient(string connectionString) => _connectionString = connectionString; + public BlobContainerClient GetBlobContainerClient(string containerName) => new BlobContainerClient(containerName); + } + + public class BlobContainerClient + { + private readonly string _containerName; + private readonly string _rootPath; + public BlobContainerClient(string containerName) + { + _containerName = containerName; + // Use a folder named "BlobStorage" in the current directory as a simple storage backing. + _rootPath = Path.Combine(Directory.GetCurrentDirectory(), "BlobStorage", _containerName); + } + public void CreateIfNotExists() + { + Directory.CreateDirectory(_rootPath); + } + public IEnumerable GetBlobs() + { + foreach (var file in Directory.EnumerateFiles(_rootPath, "*.pdf")) + { + yield return new BlobItem { Name = Path.GetFileName(file) }; + } + } + public BlobClient GetBlobClient(string blobName) => new BlobClient(Path.Combine(_rootPath, blobName)); + } + + public class BlobClient + { + private readonly string _filePath; + public BlobClient(string filePath) => _filePath = filePath; + public void DownloadTo(Stream destination) + { + using (FileStream fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read)) + { + fs.CopyTo(destination); + } + } + public void Upload(Stream source, bool overwrite) + { + var mode = overwrite ? FileMode.Create : FileMode.CreateNew; + using (FileStream fs = new FileStream(_filePath, mode, FileAccess.Write)) + { + source.CopyTo(fs); + } + } + } +} + +namespace Azure.Storage.Blobs.Models +{ + public class BlobItem + { + public string Name { get; set; } + } +} diff --git a/facades-annotations/batch-update-annotation-author.cs b/facades-annotations/batch-update-annotation-author.cs new file mode 100644 index 00000000..38f4434f --- /dev/null +++ b/facades-annotations/batch-update-annotation-author.cs @@ -0,0 +1,50 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + // Folder containing input PDF files + const string inputFolder = "input_pdfs"; + // Author to replace and the new author name + const string sourceAuthor = "Old Author"; + const string destinationAuthor = "New Author"; + + if (!Directory.Exists(inputFolder)) + { + Console.Error.WriteLine($"Folder not found: {inputFolder}"); + return; + } + + string[] pdfFiles = Directory.GetFiles(inputFolder, "*.pdf"); + if (pdfFiles.Length == 0) + { + Console.WriteLine("No PDF files found to process."); + return; + } + + foreach (string inputPath in pdfFiles) + { + // Bind the PDF to the editor + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + + // Determine the total number of pages in the document + int pageCount = editor.Document.Pages.Count; + + // Modify the author of annotations on all pages + editor.ModifyAnnotationsAuthor(1, pageCount, sourceAuthor, destinationAuthor); + + // Save the updated PDF with a simple filename (no directory path) + string outputFileName = Path.GetFileNameWithoutExtension(inputPath) + "_updated.pdf"; + editor.Save(outputFileName); + } + + Console.WriteLine($"Processed '{Path.GetFileName(inputPath)}' -> updated file saved."); + } + } +} \ No newline at end of file diff --git a/facades-annotations/benchmark-delete-annotations.cs b/facades-annotations/benchmark-delete-annotations.cs new file mode 100644 index 00000000..a75e9c08 --- /dev/null +++ b/facades-annotations/benchmark-delete-annotations.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using System.Diagnostics; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; + +public class BenchmarkDeleteAnnotations +{ + public static void Main() + { + const string inputPath = "input.pdf"; + const string outputAllPath = "output_all.pdf"; + const string outputSinglePath = "output_single.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + // Benchmark DeleteAnnotations (delete all annotations) + using (Document docAll = new Document(inputPath)) + { + PdfAnnotationEditor editorAll = new PdfAnnotationEditor(); + editorAll.BindPdf(docAll); + Stopwatch swAll = new Stopwatch(); + swAll.Start(); + editorAll.DeleteAnnotations(); + swAll.Stop(); + long elapsedAll = swAll.ElapsedMilliseconds; + editorAll.Save(outputAllPath); + editorAll.Close(); + Console.WriteLine("DeleteAnnotations elapsed (ms): " + elapsedAll); + } + + // Benchmark DeleteAnnotation (delete a single annotation by name) + using (Document docSingle = new Document(inputPath)) + { + // Retrieve the name of the first annotation on the first page + Annotation firstAnnotation = docSingle.Pages[1].Annotations[1]; + string annotationName = firstAnnotation.Name; + + PdfAnnotationEditor editorSingle = new PdfAnnotationEditor(); + editorSingle.BindPdf(docSingle); + Stopwatch swSingle = new Stopwatch(); + swSingle.Start(); + editorSingle.DeleteAnnotation(annotationName); + swSingle.Stop(); + long elapsedSingle = swSingle.ElapsedMilliseconds; + editorSingle.Save(outputSinglePath); + editorSingle.Close(); + Console.WriteLine("DeleteAnnotation elapsed (ms): " + elapsedSingle); + } + } +} diff --git a/facades-annotations/check-duplicate-annotation-names.cs b/facades-annotations/check-duplicate-annotation-names.cs new file mode 100644 index 00000000..439a1b45 --- /dev/null +++ b/facades-annotations/check-duplicate-annotation-names.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class AnnotationDuplicateChecker +{ + public static void CheckDuplicateAnnotationNames(string inputPath) + { + if (!System.IO.File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + Dictionary nameCounts = new Dictionary(StringComparer.Ordinal); + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + AnnotationCollection annotations = page.Annotations; + foreach (Annotation annotation in annotations) + { + string name = annotation.Name; + if (String.IsNullOrEmpty(name)) + { + continue; + } + + if (nameCounts.ContainsKey(name)) + { + nameCounts[name] = nameCounts[name] + 1; + } + else + { + nameCounts[name] = 1; + } + } + } + + bool duplicatesFound = false; + foreach (KeyValuePair kvp in nameCounts) + { + if (kvp.Value > 1) + { + duplicatesFound = true; + Console.WriteLine($"Duplicate annotation name \"{kvp.Key}\" found {kvp.Value} times."); + } + } + + if (!duplicatesFound) + { + Console.WriteLine("No duplicate annotation names were found."); + } + } + } + + public static void Main() + { + const string inputPdf = "input.pdf"; + CheckDuplicateAnnotationNames(inputPdf); + } +} \ No newline at end of file diff --git a/facades-annotations/clone-annotation-change-color.cs b/facades-annotations/clone-annotation-change-color.cs new file mode 100644 index 00000000..6de92540 --- /dev/null +++ b/facades-annotations/clone-annotation-change-color.cs @@ -0,0 +1,66 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + // Ensure there is at least one annotation on the first page + if (doc.Pages[1].Annotations.Count == 0) + { + Console.Error.WriteLine("No annotations found on the first page to clone."); + return; + } + + // Get the first annotation from page 1 (cast from object to Annotation) + Annotation originalAnnotation = doc.Pages[1].Annotations[1] as Annotation; + if (originalAnnotation == null) + { + Console.Error.WriteLine("Failed to retrieve the original annotation."); + return; + } + + // Clone the annotation (Clone returns object, so cast to Annotation) + Annotation clonedAnnotation = originalAnnotation.Clone() as Annotation; + if (clonedAnnotation == null) + { + Console.Error.WriteLine("Clone operation returned null. Unable to clone the annotation."); + return; + } + + // Change the color of the cloned annotation + clonedAnnotation.Color = Aspose.Pdf.Color.Red; + + // Add the cloned annotation to page 2 (create page 2 if it does not exist) + if (doc.Pages.Count < 2) + { + doc.Pages.Add(); + } + doc.Pages[2].Annotations.Add(clonedAnnotation); + + // Save the modified document + doc.Save(outputPath); + Console.WriteLine($"Cloned annotation saved to '{outputPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/clone-modify-annotation.cs b/facades-annotations/clone-modify-annotation.cs new file mode 100644 index 00000000..c1d2a67a --- /dev/null +++ b/facades-annotations/clone-modify-annotation.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "cloned_annotation.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + // Get the first page (pages are 1‑based) + Page page = doc.Pages[1]; + + // Ensure the page contains at least one annotation + if (page.Annotations.Count > 0) + { + // Retrieve the first annotation on the page + Annotation originalAnnotation = page.Annotations[1]; + + // Clone the annotation – Clone returns object, so cast to Annotation + Annotation clonedAnnotation = originalAnnotation.Clone() as Annotation; + + if (clonedAnnotation != null) + { + // Modify desired properties of the cloned annotation + clonedAnnotation.Color = Aspose.Pdf.Color.Red; + clonedAnnotation.Contents = "This is a cloned annotation"; + + // Title exists only on markup‑type annotations, so cast before setting it + if (clonedAnnotation is MarkupAnnotation markup) + { + markup.Title = "Cloned Annotation"; + } + else + { + Console.Error.WriteLine("Cloned annotation is not a markup annotation; Title cannot be set."); + } + + // Add the cloned annotation back to the same page + page.Annotations.Add(clonedAnnotation); + } + else + { + Console.Error.WriteLine("Clone() returned null – cloning not supported for this annotation type."); + } + } + else + { + Console.Error.WriteLine("No annotations found on the first page to clone."); + } + + // Save the modified document + doc.Save(outputPath); + Console.WriteLine($"Document saved as '{outputPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/compare-annotation-counts.cs b/facades-annotations/compare-annotation-counts.cs new file mode 100644 index 00000000..4ab19e25 --- /dev/null +++ b/facades-annotations/compare-annotation-counts.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Load the PDF and count existing annotations + using (Document doc = new Document(inputPath)) + { + int initialCount = 0; + foreach (Page page in doc.Pages) + { + initialCount += page.Annotations.Count; + } + Console.WriteLine($"Initial annotation count: {initialCount}"); + + // Delete all annotations using PdfAnnotationEditor + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(doc); + editor.DeleteAnnotations(); + editor.Save(outputPath); + editor.Close(); + + // Count annotations after deletion + int afterCount = 0; + foreach (Page page in doc.Pages) + { + afterCount += page.Annotations.Count; + } + Console.WriteLine($"Annotation count after deletion: {afterCount}"); + } + } +} diff --git a/facades-annotations/concurrent-import-delete.cs b/facades-annotations/concurrent-import-delete.cs new file mode 100644 index 00000000..4c55f72f --- /dev/null +++ b/facades-annotations/concurrent-import-delete.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string importPath = "source.pdf"; + const string deleteOutputPath = "deleted_output.pdf"; + const string importOutputPath = "imported_output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input PDF not found: " + inputPath); + return; + } + if (!File.Exists(importPath)) + { + Console.Error.WriteLine("Import PDF not found: " + importPath); + return; + } + + Task deleteTask = Task.Run(() => + { + PdfFileEditor editor = new PdfFileEditor(); + int[] pagesToDelete = new int[] { 2 }; + bool result = editor.TryDelete(inputPath, pagesToDelete, deleteOutputPath); + Console.WriteLine("Delete task completed: " + result); + }); + + Task importTask = Task.Run(() => + { + using (Document targetDoc = new Document(inputPath)) + { + using (Document sourceDoc = new Document(importPath)) + { + targetDoc.Pages.Add(sourceDoc.Pages); + targetDoc.Save(importOutputPath); + } + } + Console.WriteLine("Import task completed."); + }); + + Task.WaitAll(deleteTask, importTask); + Console.WriteLine("Concurrent operations finished."); + } +} \ No newline at end of file diff --git a/facades-annotations/copy-annotations-template-to-multiple.cs b/facades-annotations/copy-annotations-template-to-multiple.cs new file mode 100644 index 00000000..49028ceb --- /dev/null +++ b/facades-annotations/copy-annotations-template-to-multiple.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string templatePath = "template.pdf"; + string[] targetPaths = new string[] { "target1.pdf", "target2.pdf" }; + + if (!File.Exists(templatePath)) + { + Console.Error.WriteLine("Template file not found: " + templatePath); + return; + } + + // Export annotations from the template PDF to an in‑memory XFDF stream + using (PdfAnnotationEditor templateEditor = new PdfAnnotationEditor()) + { + templateEditor.BindPdf(templatePath); + using (MemoryStream xfdfStream = new MemoryStream()) + { + templateEditor.ExportAnnotationsToXfdf(xfdfStream); + // Prepare the stream for reading + xfdfStream.Position = 0; + + foreach (string targetPath in targetPaths) + { + if (!File.Exists(targetPath)) + { + Console.Error.WriteLine("Target file not found: " + targetPath); + continue; + } + + using (PdfAnnotationEditor targetEditor = new PdfAnnotationEditor()) + { + targetEditor.BindPdf(targetPath); + // Reset stream position before each import + xfdfStream.Position = 0; + targetEditor.ImportAnnotationsFromXfdf(xfdfStream); + string outputFileName = Path.GetFileNameWithoutExtension(targetPath) + "_with_annots.pdf"; + targetEditor.Save(outputFileName); + Console.WriteLine("Annotations copied to: " + outputFileName); + } + } + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/count-pdf-annotation-types.cs b/facades-annotations/count-pdf-annotation-types.cs new file mode 100644 index 00000000..dc853059 --- /dev/null +++ b/facades-annotations/count-pdf-annotation-types.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +public class Program +{ + /// + /// Returns a dictionary that maps each annotation type present in the PDF to the number of its occurrences. + /// If the input file does not exist, a minimal placeholder PDF is created automatically. + /// + public static Dictionary CountAnnotationTypes(string pdfPath) + { + // Ensure the file exists – create a minimal placeholder PDF if it does not. + if (!File.Exists(pdfPath)) + { + // Create a one‑page PDF with no content. + using var placeholder = new Document(); + placeholder.Pages.Add(); + placeholder.Save(pdfPath); + } + + using (Document doc = new Document(pdfPath)) + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor(doc)) + { + int startPage = 1; + int endPage = doc.Pages.Count; + Aspose.Pdf.Annotations.AnnotationType[] allTypes = (Aspose.Pdf.Annotations.AnnotationType[])Enum.GetValues(typeof(Aspose.Pdf.Annotations.AnnotationType)); + IList annotations = editor.ExtractAnnotations(startPage, endPage, allTypes); + + var counts = new Dictionary(); + foreach (Annotation annotation in annotations) + { + Aspose.Pdf.Annotations.AnnotationType type = annotation.AnnotationType; + if (counts.ContainsKey(type)) + { + counts[type] = counts[type] + 1; + } + else + { + counts[type] = 1; + } + } + return counts; + } + } + } + + public static void Main() + { + const string inputPath = "input.pdf"; + Dictionary annotationCounts = CountAnnotationTypes(inputPath); + foreach (KeyValuePair entry in annotationCounts) + { + Console.WriteLine($"{entry.Key}: {entry.Value}"); + } + } +} diff --git a/facades-annotations/delete-all-annotations.cs b/facades-annotations/delete-all-annotations.cs new file mode 100644 index 00000000..23e64d61 --- /dev/null +++ b/facades-annotations/delete-all-annotations.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.DeleteAnnotations(); + editor.Save(outputPath); + } + + Console.WriteLine($"All annotations removed. Saved to '{outputPath}'."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/delete-annotation-by-name.cs b/facades-annotations/delete-annotation-by-name.cs new file mode 100644 index 00000000..e3676e16 --- /dev/null +++ b/facades-annotations/delete-annotation-by-name.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + // Ensure the input PDF exists. If it does not, create a minimal PDF with the target annotation. + if (!File.Exists(inputPath)) + { + CreateSamplePdfWithAnnotation(inputPath); + } + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + // Delete the annotation named "Comment1" + editor.DeleteAnnotation("Comment1"); + editor.Save(outputPath); + } + } + + private static void CreateSamplePdfWithAnnotation(string path) + { + // Create a new PDF document with a single page. + using (Document doc = new Document()) + { + Page page = doc.Pages.Add(); + + // Define a rectangle for the annotation (coordinates are in points). + // Use Aspose.Pdf.Rectangle (annotation bounds) – lower‑left X/Y and upper‑right X/Y. + var rect = new Aspose.Pdf.Rectangle(100, 600, 200, 700); + + // Create a text annotation and give it the required name. + var comment = new TextAnnotation(page, rect) + { + Name = "Comment1", + Title = "Sample Comment", + Contents = "This is a sample comment annotation." + }; + + // Add the annotation to the page. + page.Annotations.Add(comment); + + // Save the PDF to the specified path. + doc.Save(path); + } + } +} diff --git a/facades-annotations/delete-annotation-by-name__v2.cs b/facades-annotations/delete-annotation-by-name__v2.cs new file mode 100644 index 00000000..7270f6a5 --- /dev/null +++ b/facades-annotations/delete-annotation-by-name__v2.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string annotationName = "4cfa69cd-9bff-49e0-9005-e22a77cebf38"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + Aspose.Pdf.Facades.PdfAnnotationEditor editor = new Aspose.Pdf.Facades.PdfAnnotationEditor(); + editor.BindPdf(inputPath); + editor.DeleteAnnotation(annotationName); + editor.Save(outputPath); + Console.WriteLine($"Annotation '{annotationName}' deleted. Saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotation-error-handling.cs b/facades-annotations/delete-annotation-error-handling.cs new file mode 100644 index 00000000..60d04e44 --- /dev/null +++ b/facades-annotations/delete-annotation-error-handling.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string annotationName = "nonexistent-annotation-id"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + try + { + editor.DeleteAnnotation(annotationName); + Console.WriteLine($"Annotation '{annotationName}' deleted."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Failed to delete annotation '{annotationName}': {ex.Message}"); + } + + editor.Save(outputPath); + } + + Console.WriteLine($"Result saved to '{outputPath}'."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Unexpected error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotations-by-author.cs b/facades-annotations/delete-annotations-by-author.cs new file mode 100644 index 00000000..1ef4ec1d --- /dev/null +++ b/facades-annotations/delete-annotations-by-author.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string targetAuthor = "John Doe"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + foreach (Page page in doc.Pages) + { + // 1. Filter annotations whose author information matches the target. + // In Aspose.Pdf the author is stored in the Subject property of a MarkupAnnotation. + var indicesToDelete = new List(); + + for (int i = 1; i <= page.Annotations.Count; i++) + { + Annotation ann = page.Annotations[i]; + if (ann is MarkupAnnotation markup && + !string.IsNullOrEmpty(markup.Subject) && + markup.Subject.Equals(targetAuthor, StringComparison.OrdinalIgnoreCase)) + { + indicesToDelete.Add(i); + } + } + + // 2. Delete the filtered annotations. Deleting from highest index to lowest + // preserves the validity of the remaining indices. + indicesToDelete.Sort((a, b) => b.CompareTo(a)); + foreach (int idx in indicesToDelete) + { + page.Annotations.Delete(idx); + } + } + + doc.Save(outputPath); + Console.WriteLine($"Annotations by '{targetAuthor}' removed. Saved to '{outputPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/delete-annotations-by-color.cs b/facades-annotations/delete-annotations-by-color.cs new file mode 100644 index 00000000..dfe105d2 --- /dev/null +++ b/facades-annotations/delete-annotations-by-color.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Define the target color (e.g., pure red) + Aspose.Pdf.Color targetColor = Aspose.Pdf.Color.FromRgb(1.0, 0.0, 0.0); + + using (Document doc = new Document(inputPath)) + { + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + // Iterate backwards because deleting changes the collection indexing + for (int annIndex = page.Annotations.Count; annIndex >= 1; annIndex--) + { + Annotation annotation = page.Annotations[annIndex]; + if (annotation.Color != null && annotation.Color.Equals(targetColor)) + { + page.Annotations.Delete(annIndex); + } + } + } + + doc.Save(outputPath); + } + + Console.WriteLine($"Annotations with the specified color removed. Saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotations-by-name.cs b/facades-annotations/delete-annotations-by-name.cs new file mode 100644 index 00000000..18dc44da --- /dev/null +++ b/facades-annotations/delete-annotations-by-name.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPathLiteral = "output_literal.pdf"; + const string outputPathVariable = "output_variable.pdf"; + + // Ensure the input PDF exists and contains the annotations we will delete. + if (!File.Exists(inputPath)) + { + CreateSamplePdfWithAnnotation(inputPath); + } + + // Delete annotation using a string literal + using (PdfAnnotationEditor editorLiteral = new PdfAnnotationEditor()) + { + editorLiteral.BindPdf(inputPath); + editorLiteral.DeleteAnnotation("4cfa69cd-9bff-49e0-9005-e22a77cebf38"); + editorLiteral.Save(outputPathLiteral); + } + + // Delete annotation using a variable + string annotationName = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"; + using (PdfAnnotationEditor editorVariable = new PdfAnnotationEditor()) + { + editorVariable.BindPdf(inputPath); + editorVariable.DeleteAnnotation(annotationName); + editorVariable.Save(outputPathVariable); + } + } + + private static void CreateSamplePdfWithAnnotation(string path) + { + // Create a simple one‑page PDF document. + var doc = new Document(); + var page = doc.Pages.Add(); + + // First annotation – will be removed using a string literal. + var annotationLiteral = new TextAnnotation(page, new Aspose.Pdf.Rectangle(100, 600, 200, 650)) + { + Name = "4cfa69cd-9bff-49e0-9005-e22a77cebf38", + Title = "Literal", + Contents = "Annotation to be deleted via literal." + }; + page.Annotations.Add(annotationLiteral); + + // Second annotation – will be removed using a variable. + var annotationVariable = new TextAnnotation(page, new Aspose.Pdf.Rectangle(100, 500, 200, 550)) + { + Name = "a1b2c3d4-e5f6-7890-abcd-ef1234567890", + Title = "Variable", + Contents = "Annotation to be deleted via variable." + }; + page.Annotations.Add(annotationVariable); + + doc.Save(path); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotations-export-xfdf.cs b/facades-annotations/delete-annotations-export-xfdf.cs new file mode 100644 index 00000000..0ce84ac8 --- /dev/null +++ b/facades-annotations/delete-annotations-export-xfdf.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + // --------------------------------------------------------------------- + // 1. Prepare a sample PDF with a Text annotation (so the file always exists + // when the demo runs). This eliminates the FileNotFoundException that + // occurred in the original code. + // --------------------------------------------------------------------- + string inputPdf = Path.Combine(Path.GetTempPath(), "sample_input.pdf"); + CreateSamplePdfWithTextAnnotation(inputPdf); + + string outputPdf = Path.Combine(Path.GetTempPath(), "sample_output.pdf"); + string xfdfFile = Path.Combine(Path.GetTempPath(), "remaining_annotations.xfdf"); + + // --------------------------------------------------------------------- + // 2. Delete all annotations of type "Text" and export the remaining ones + // to an XFDF file. + // --------------------------------------------------------------------- + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + // Bind the existing PDF document. + editor.BindPdf(inputPdf); + + // Delete every annotation whose type name is "Text". + // The method accepts the annotation type as a string (e.g., "Text", + // "Link", "Highlight", etc.). + editor.DeleteAnnotations("Text"); + + // Save the PDF after the deletion. + editor.Save(outputPdf); + + // Export the *remaining* annotations (if any) to an XFDF file. + using (FileStream xfdfStream = File.Create(xfdfFile)) + { + editor.ExportAnnotationsToXfdf(xfdfStream); + } + } + + Console.WriteLine($"Input PDF : {inputPdf}"); + Console.WriteLine($"Output PDF : {outputPdf}"); + Console.WriteLine($"XFDF export : {xfdfFile}"); + Console.WriteLine("Text annotations deleted and remaining annotations exported to XFDF."); + } + + /// + /// Creates a one‑page PDF containing a single Text annotation. + /// This helper guarantees that the demo has a valid source file. + /// + private static void CreateSamplePdfWithTextAnnotation(string filePath) + { + // Create a new PDF document. + using (Document doc = new Document()) + { + // Add a blank page. + Page page = doc.Pages.Add(); + + // Create a Text annotation (the type we will later delete). + TextAnnotation txtAnn = new TextAnnotation(page, new Aspose.Pdf.Rectangle(100, 600, 300, 650)) + { + Title = "Sample", + Subject = "Demo", + Contents = "This is a sample text annotation." + }; + + // Add the annotation to the page. + page.Annotations.Add(txtAnn); + + // Save the PDF to the supplied path. + doc.Save(filePath); + } + } +} diff --git a/facades-annotations/delete-annotations-folder.cs b/facades-annotations/delete-annotations-folder.cs new file mode 100644 index 00000000..a41036a3 --- /dev/null +++ b/facades-annotations/delete-annotations-folder.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +public class Program +{ + public static void Main(string[] args) + { + if (args.Length < 1) + { + Console.Error.WriteLine("Usage: DeleteAnnotations "); + return; + } + + string folderPath = args[0]; + if (!Directory.Exists(folderPath)) + { + Console.Error.WriteLine($"Folder not found: {folderPath}"); + return; + } + + string[] pdfFiles = Directory.GetFiles(folderPath, "*.pdf"); + foreach (string pdfPath in pdfFiles) + { + string fileName = Path.GetFileName(pdfPath); + string outputFileName = "clean_" + fileName; // simple filename, no path + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(pdfPath); + editor.DeleteAnnotations(); + editor.Save(outputFileName); + } + + Console.WriteLine($"Processed {fileName} -> {outputFileName}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotations-from-config.cs b/facades-annotations/delete-annotations-from-config.cs new file mode 100644 index 00000000..d5532d72 --- /dev/null +++ b/facades-annotations/delete-annotations-from-config.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPdfPath = "input.pdf"; + const string configFilePath = "annotations_to_delete.txt"; + const string outputPdfPath = "output.pdf"; + + if (!File.Exists(inputPdfPath)) + { + Console.Error.WriteLine($"Input PDF not found: {inputPdfPath}"); + return; + } + if (!File.Exists(configFilePath)) + { + Console.Error.WriteLine($"Configuration file not found: {configFilePath}"); + return; + } + + // Read annotation types (one per line) from the configuration file + string[] annotationTypes = File.ReadAllLines(configFilePath); + + // Use PdfAnnotationEditor to delete specified annotation types + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPdfPath); + + foreach (string rawType in annotationTypes) + { + string type = rawType.Trim(); + if (type.Length == 0) + { + continue; // skip empty lines + } + // Delete all annotations of this type + editor.DeleteAnnotations(type); + } + + editor.Save(outputPdfPath); + } + + Console.WriteLine($"Annotations deleted as per configuration. Output saved to '{outputPdfPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotations-parallel.cs b/facades-annotations/delete-annotations-parallel.cs new file mode 100644 index 00000000..09bb2b1c --- /dev/null +++ b/facades-annotations/delete-annotations-parallel.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + string inputDirectory = "input-pdfs"; + string outputDirectory = "output-pdfs"; + + if (!Directory.Exists(inputDirectory)) + { + Console.Error.WriteLine($"Input directory not found: {inputDirectory}"); + return; + } + + Directory.CreateDirectory(outputDirectory); + + string[] pdfFiles = Directory.GetFiles(inputDirectory, "*.pdf", SearchOption.TopDirectoryOnly); + + ConcurrentBag errors = new ConcurrentBag(); + + Parallel.ForEach(pdfFiles, pdfPath => + { + try + { + string fileName = Path.GetFileName(pdfPath); + string outputPath = Path.Combine(outputDirectory, fileName); + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(pdfPath); + editor.DeleteAnnotations(); + editor.Save(outputPath); + } + } + catch (Exception ex) + { + errors.Add($"{pdfPath}: {ex.Message}"); + } + }); + + if (!errors.IsEmpty) + { + Console.Error.WriteLine("Some files could not be processed:"); + foreach (string err in errors) + { + Console.Error.WriteLine(err); + } + } + else + { + Console.WriteLine("All PDFs processed successfully."); + } + } +} diff --git a/facades-annotations/delete-annotations-unit-test.cs b/facades-annotations/delete-annotations-unit-test.cs new file mode 100644 index 00000000..e80b1749 --- /dev/null +++ b/facades-annotations/delete-annotations-unit-test.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; +using System.Diagnostics; + +class DeleteAnnotationsUnitTest +{ + static void Main() + { + // Create a PDF with a single annotation + string originalPath = "original.pdf"; + string cleanedPath = "cleaned.pdf"; + + using (Document doc = new Document()) + { + Page page = doc.Pages.Add(); + TextAnnotation annotation = new TextAnnotation(page, new Aspose.Pdf.Rectangle(100, 500, 200, 550)) + { + Title = "Note", + Contents = "Sample annotation", + Open = true, + Color = Aspose.Pdf.Color.Yellow + }; + page.Annotations.Add(annotation); + doc.Save(originalPath); + } + + // Verify the annotation exists + using (Document doc = new Document(originalPath)) + { + Page page = doc.Pages[1]; + int initialCount = page.Annotations.Count; + if (initialCount != 1) + { + throw new Exception($"Expected 1 annotation before deletion, found {initialCount}."); + } + } + + // Delete all annotations using PdfAnnotationEditor + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(originalPath); + editor.DeleteAnnotations(); + editor.Save(cleanedPath); + editor.Close(); + + // Verify that all annotations have been removed + using (Document doc = new Document(cleanedPath)) + { + Page page = doc.Pages[1]; + int finalCount = page.Annotations.Count; + if (finalCount != 0) + { + throw new Exception($"Expected 0 annotations after deletion, found {finalCount}."); + } + } + + Console.WriteLine("DeleteAnnotations unit test passed."); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-annotations-with-backup.cs b/facades-annotations/delete-annotations-with-backup.cs new file mode 100644 index 00000000..97e8155f --- /dev/null +++ b/facades-annotations/delete-annotations-with-backup.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string backupPath = "input_backup.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Create a backup copy of the original PDF + File.Copy(inputPath, backupPath, true); + + // Delete all annotations using PdfAnnotationEditor + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + editor.DeleteAnnotations(); + editor.Save(outputPath); + editor.Close(); + + Console.WriteLine($"Backup created at '{backupPath}'. Annotations removed, result saved to '{outputPath}'."); + } +} diff --git a/facades-annotations/delete-annotations-with-logging.cs b/facades-annotations/delete-annotations-with-logging.cs new file mode 100644 index 00000000..6dfa340f --- /dev/null +++ b/facades-annotations/delete-annotations-with-logging.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string logPath = "deletion_log.txt"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("File not found: " + inputPath); + return; + } + + using (Document doc = new Document(inputPath)) + { + using (StreamWriter logWriter = new StreamWriter(logPath, false)) + { + // Write CSV header + logWriter.WriteLine("AnnotationName,AnnotationType,PageNumber"); + + // Pages are 1‑based + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + AnnotationCollection annotations = page.Annotations; + + // Copy current annotations to an array to avoid modifying the collection while iterating + Annotation[] annotationArray = new Annotation[annotations.Count]; + for (int i = 0; i < annotations.Count; i++) + { + annotationArray[i] = annotations[i]; + } + + foreach (Annotation annotation in annotationArray) + { + string name = annotation.Name ?? string.Empty; + string type = annotation.GetType().Name; + int pageNumber = pageIndex; + + // Log deletion details + logWriter.WriteLine($"{name},{type},{pageNumber}"); + + // Delete the annotation from the page + annotations.Delete(annotation); + } + } + } + + // Save the PDF without the deleted annotations + doc.Save(outputPath); + } + + Console.WriteLine("Annotations deleted and logged to " + logPath); + } +} diff --git a/facades-annotations/delete-flatten-annotations.cs b/facades-annotations/delete-flatten-annotations.cs new file mode 100644 index 00000000..b232c191 --- /dev/null +++ b/facades-annotations/delete-flatten-annotations.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.DeleteAnnotations(); + editor.FlatteningAnnotations(); + editor.Save(outputPath); + } + + Console.WriteLine($"Processed PDF saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-pdf-annotation-retry.cs b/facades-annotations/delete-pdf-annotation-retry.cs new file mode 100644 index 00000000..53e4530f --- /dev/null +++ b/facades-annotations/delete-pdf-annotation-retry.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string annotationName = "4cfa69cd-9bff-49e0-9005-e22a77cebf38"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + const int maxAttempts = 2; + int attempt = 0; + bool deleted = false; + + while (attempt < maxAttempts && !deleted) + { + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + try + { + editor.BindPdf(inputPath); + editor.DeleteAnnotation(annotationName); + editor.Save(outputPath); + deleted = true; + } + catch (Exception ex) + { + Console.Error.WriteLine("Attempt " + (attempt + 1) + " failed: " + ex.Message); + // If not the last attempt, the loop will retry after re‑binding. + } + finally + { + editor.Close(); + } + attempt++; + } + + if (deleted) + { + Console.WriteLine("Annotation deleted and saved to '" + outputPath + "'."); + } + else + { + Console.Error.WriteLine("Failed to delete annotation after retries."); + } + } +} diff --git a/facades-annotations/delete-pdf-annotations.cs b/facades-annotations/delete-pdf-annotations.cs new file mode 100644 index 00000000..bbae2c68 --- /dev/null +++ b/facades-annotations/delete-pdf-annotations.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + string folderPath = "pdfs"; + if (!Directory.Exists(folderPath)) + { + Console.Error.WriteLine($"Folder not found: {folderPath}"); + return; + } + + string[] pdfFiles = Directory.GetFiles(folderPath, "*.pdf"); + foreach (string pdfPath in pdfFiles) + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(pdfPath); + editor.DeleteAnnotations(); + // Overwrite the original file + editor.Save(pdfPath); + } + } + + Console.WriteLine("All annotations have been removed from PDFs in the folder."); + } +} \ No newline at end of file diff --git a/facades-annotations/delete-text-annotations.cs b/facades-annotations/delete-text-annotations.cs new file mode 100644 index 00000000..e0765ac2 --- /dev/null +++ b/facades-annotations/delete-text-annotations.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.DeleteAnnotations("Text"); + editor.Save(outputPath); + } + + Console.WriteLine($"Text annotations deleted. Saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/diagnostic-annotation-workflow.cs b/facades-annotations/diagnostic-annotation-workflow.cs new file mode 100644 index 00000000..6b89da0c --- /dev/null +++ b/facades-annotations/diagnostic-annotation-workflow.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "annotated.pdf"; + const string logPath = "annotation_log.txt"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + using (StreamWriter logger = new StreamWriter(logPath, false)) + { + logger.WriteLine("Annotation workflow started at " + DateTime.Now); + + using (Document doc = new Document(inputPath)) + { + logger.WriteLine("Loaded document: " + inputPath); + logger.WriteLine("Page count: " + doc.Pages.Count); + + // Add a LinkAnnotation on the first page + Aspose.Pdf.Rectangle linkRect = new Aspose.Pdf.Rectangle(100, 500, 200, 550); + LinkAnnotation link = new LinkAnnotation(doc.Pages[1], linkRect); + link.Action = new GoToURIAction("https://www.example.com"); + link.Color = Aspose.Pdf.Color.Blue; + doc.Pages[1].Annotations.Add(link); + logger.WriteLine("Added LinkAnnotation to page 1 with rectangle " + linkRect.ToString()); + + // Add a TextAnnotation on the first page + Aspose.Pdf.Rectangle textRect = new Aspose.Pdf.Rectangle(100, 400, 300, 450); + TextAnnotation textAnn = new TextAnnotation(doc.Pages[1], textRect); + textAnn.Title = "Note"; + textAnn.Contents = "This is a sample text annotation."; + textAnn.Color = Aspose.Pdf.Color.Yellow; + doc.Pages[1].Annotations.Add(textAnn); + logger.WriteLine("Added TextAnnotation to page 1 with rectangle " + textRect.ToString()); + + // Save the annotated document + doc.Save(outputPath); + logger.WriteLine("Saved annotated document as " + outputPath); + } + + logger.WriteLine("Annotation workflow completed at " + DateTime.Now); + } + + Console.WriteLine("Process completed. See " + logPath); + } +} \ No newline at end of file diff --git a/facades-annotations/export-annotations-empty-pdf.cs b/facades-annotations/export-annotations-empty-pdf.cs new file mode 100644 index 00000000..24220525 --- /dev/null +++ b/facades-annotations/export-annotations-empty-pdf.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using System.Text; +using Aspose.Pdf; + +// Minimal NUnit stubs to allow compilation without the NUnit package +namespace NUnit.Framework +{ + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestFixtureAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class TestAttribute : Attribute { } + + public static class Assert + { + public static void AreEqual(T expected, T actual, string message = null) + { + if (!object.Equals(expected, actual)) + throw new Exception(message ?? $"Assert.AreEqual failed. Expected:<{expected}>. Actual:<{actual}>."); + } + + public static void IsTrue(bool condition, string message = null) + { + if (!condition) + throw new Exception(message ?? "Assert.IsTrue failed."); + } + } +} + +namespace AsposePdfTests +{ + // Bring the NUnit attributes into this namespace after the stub definition + using NUnit.Framework; + + [TestFixture] + public class ExportAnnotationsTests + { + [Test] + public void ExportAnnotations_EmptyPdf_ShouldProduceValidXfdf() + { + // Create a PDF with a single blank page + using (Document document = new Document()) + { + Page page = document.Pages.Add(); + + // Verify that the page contains no annotations + Assert.AreEqual(0, page.Annotations.Count); + + // Export annotations to XFDF using a memory stream + using (MemoryStream stream = new MemoryStream()) + { + document.ExportAnnotationsToXfdf(stream); + stream.Position = 0; + using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) + { + string xfdfContent = reader.ReadToEnd(); + // Basic validation: the XFDF root element should be present + Assert.IsTrue(xfdfContent.Contains(" !a.IsNamespaceDeclaration), + // Recursively copy child elements with the new namespace + xfdfDoc.Root.Elements().Select(e => ChangeNamespace(e, newNs)) + ) + ); + + using (FileStream fileStream = new FileStream(outputXfdf, FileMode.Create, FileAccess.Write)) + { + newXfdf.Save(fileStream); + } + } + } + } + } + + /// + /// Recursively creates a copy of an element (and its descendants) using the supplied namespace. + /// + private static XElement ChangeNamespace(XElement element, XNamespace newNs) + { + return new XElement( + newNs + element.Name.LocalName, + // Preserve non‑namespace attributes + element.Attributes().Where(a => !a.IsNamespaceDeclaration), + // Recurse into children + element.Elements().Select(e => ChangeNamespace(e, newNs)) + ); + } +} diff --git a/facades-annotations/export-annotations-xfdf-gzip.cs b/facades-annotations/export-annotations-xfdf-gzip.cs new file mode 100644 index 00000000..ef23afa0 --- /dev/null +++ b/facades-annotations/export-annotations-xfdf-gzip.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.IO.Compression; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "annotations.xfdf.gz"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + using (Document doc = new Document(inputPath)) + { + using (MemoryStream xfdfStream = new MemoryStream()) + { + doc.ExportAnnotationsToXfdf(xfdfStream); + xfdfStream.Position = 0; + + using (FileStream fileStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) + { + using (GZipStream gzipStream = new GZipStream(fileStream, CompressionMode.Compress)) + { + xfdfStream.CopyTo(gzipStream); + } + } + } + } + + Console.WriteLine("Annotations exported and compressed to '" + outputPath + "'."); + } +} \ No newline at end of file diff --git a/facades-annotations/export-annotations-xfdf-log.cs b/facades-annotations/export-annotations-xfdf-log.cs new file mode 100644 index 00000000..71696e47 --- /dev/null +++ b/facades-annotations/export-annotations-xfdf-log.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string xfdfLogPath = "export_log.xfdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + // Perform the primary export operation (PDF save in this example) + doc.Save(outputPath); + Console.WriteLine($"PDF saved to '{outputPath}'."); + + // Diagnostic: write full XFDF content of all annotations to a log file + doc.ExportAnnotationsToXfdf(xfdfLogPath); + Console.WriteLine($"XFDF log written to '{xfdfLogPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/export-annotations-xfdf.cs b/facades-annotations/export-annotations-xfdf.cs new file mode 100644 index 00000000..5aa98468 --- /dev/null +++ b/facades-annotations/export-annotations-xfdf.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Load the PDF document + using (Document document = new Document(inputPath)) + { + // Initialize the annotation editor facade + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(document); + + // Export annotations from pages 1 to 2 into an in‑memory XFDF stream + using (MemoryStream xfdfStream = new MemoryStream()) + { + // Pass null for annotation types to export all types (or specify a string[] of types) + editor.ExportAnnotationsXfdf(xfdfStream, 1, 2, (string[])null); + xfdfStream.Position = 0; // Reset for reading or further processing + + // Example: read the XFDF content as a string (optional) + using (StreamReader reader = new StreamReader(xfdfStream)) + { + string xfdfContent = reader.ReadToEnd(); + Console.WriteLine($"Exported XFDF size: {xfdfContent.Length} characters"); + } + } + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/export-delete-archive-annotations.cs b/facades-annotations/export-delete-archive-annotations.cs new file mode 100644 index 00000000..18255b31 --- /dev/null +++ b/facades-annotations/export-delete-archive-annotations.cs @@ -0,0 +1,84 @@ +using System; +using System.IO; +using System.IO.Compression; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + // Input folder containing PDF files + string inputFolder = "input"; + // Output folder for cleaned PDFs + string outputFolder = "output"; + // Archive file for all XFDF files + string archivePath = "annotations.zip"; + + // Ensure input and output folders exist + if (!Directory.Exists(inputFolder)) + { + // Create the folder so the program can run without throwing an exception. + // In a real‑world scenario you might want to abort or prompt the user. + Directory.CreateDirectory(inputFolder); + Console.WriteLine($"Input folder '{inputFolder}' did not exist and was created. Place PDF files there and re‑run the program."); + } + if (!Directory.Exists(outputFolder)) + { + Directory.CreateDirectory(outputFolder); + } + + // Process each PDF file in the input folder + string[] pdfFiles = Directory.GetFiles(inputFolder, "*.pdf"); + foreach (string pdfFile in pdfFiles) + { + // Determine file names for XFDF and cleaned PDF + string pdfFileName = Path.GetFileName(pdfFile); + string xfdfFileName = Path.ChangeExtension(pdfFileName, ".xfdf"); + string xfdfFilePath = Path.Combine(outputFolder, xfdfFileName); // store XFDF next to cleaned PDF + string cleanedPdfFileName = Path.GetFileNameWithoutExtension(pdfFileName) + "_clean.pdf"; + string cleanedPdfPath = Path.Combine(outputFolder, cleanedPdfFileName); + + // Export annotations to XFDF and delete them from the document + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(pdfFile); + + // Export all annotations to XFDF file + using (FileStream xfdfStream = File.Create(xfdfFilePath)) + { + editor.ExportAnnotationsToXfdf(xfdfStream); + } + + // Delete all annotations + editor.DeleteAnnotations(); + + // Save the PDF without annotations + editor.Save(cleanedPdfPath); + } + } + + // Archive all generated XFDF files into a zip archive + using (FileStream zipStream = new FileStream(archivePath, FileMode.Create)) + using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update)) + { + // All XFDF files are stored in the output folder + string[] xfdfFiles = Directory.GetFiles(outputFolder, "*.xfdf"); + foreach (string xfdfFile in xfdfFiles) + { + string entryName = Path.GetFileName(xfdfFile); + ZipArchiveEntry entry = archive.CreateEntry(entryName); + using (Stream entryStream = entry.Open()) + using (FileStream sourceStream = File.OpenRead(xfdfFile)) + { + sourceStream.CopyTo(entryStream); + } + } + } + + // Optional: delete individual XFDF files after archiving + // string[] xfdfFilesToDelete = Directory.GetFiles(outputFolder, "*.xfdf"); + // foreach (string file in xfdfFilesToDelete) { File.Delete(file); } + + Console.WriteLine("Annotation export, deletion, and archiving completed."); + } +} diff --git a/facades-annotations/export-highlight-annotations.cs b/facades-annotations/export-highlight-annotations.cs new file mode 100644 index 00000000..9122f5cd --- /dev/null +++ b/facades-annotations/export-highlight-annotations.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPdf = "input.pdf"; + const string outputXfdf = "highlights.xfdf"; + + if (!File.Exists(inputPdf)) + { + Console.Error.WriteLine($"File not found: {inputPdf}"); + return; + } + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPdf); + string[] annotTypes = new string[] { "Highlight" }; + int startPage = 1; + int endPage = editor.Document.Pages.Count; + using (FileStream fs = File.Create(outputXfdf)) + { + editor.ExportAnnotationsXfdf(fs, startPage, endPage, annotTypes); + } + } + + Console.WriteLine($"Highlight annotations exported to '{outputXfdf}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/export-import-annotations-xfdf.cs b/facades-annotations/export-import-annotations-xfdf.cs new file mode 100644 index 00000000..e8a1f56b --- /dev/null +++ b/facades-annotations/export-import-annotations-xfdf.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string sourcePdf = "source.pdf"; + const string targetPdf = "target.pdf"; + const string xfdfFile = "annotations.xfdf"; + const string outputPdf = "target_with_annots.pdf"; + + if (!File.Exists(sourcePdf)) + { + Console.Error.WriteLine($"Source file not found: {sourcePdf}"); + return; + } + if (!File.Exists(targetPdf)) + { + Console.Error.WriteLine($"Target file not found: {targetPdf}"); + return; + } + + // Export all annotations from the source PDF to an XFDF file + using (Document srcDoc = new Document(sourcePdf)) + { + srcDoc.ExportAnnotationsToXfdf(xfdfFile); + } + + // Import the XFDF annotations into the target PDF and save the result + using (Document tgtDoc = new Document(targetPdf)) + { + tgtDoc.ImportAnnotationsFromXfdf(xfdfFile); + tgtDoc.Save(outputPdf); + } + + Console.WriteLine($"Annotations exported to '{xfdfFile}' and imported into '{outputPdf}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/export-pdf-annotations-json.cs b/facades-annotations/export-pdf-annotations-json.cs new file mode 100644 index 00000000..03582fa2 --- /dev/null +++ b/facades-annotations/export-pdf-annotations-json.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Text.Json; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class AnnotationInfo +{ + public int PageNumber { get; set; } + public string AnnotationType { get; set; } + public RectangleBounds Bounds { get; set; } + public string Color { get; set; } + public string Contents { get; set; } + public string Title { get; set; } +} + +public class RectangleBounds +{ + public double LLX { get; set; } + public double LLY { get; set; } + public double URX { get; set; } + public double URY { get; set; } +} + +public class Program +{ + public static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "annotations_log.json"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input PDF not found: " + inputPath); + return; + } + + using (Document doc = new Document(inputPath)) + { + List annotationList = new List(); + + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + for (int annIndex = 1; annIndex <= page.Annotations.Count; annIndex++) + { + Annotation annotation = page.Annotations[annIndex]; + AnnotationInfo info = new AnnotationInfo(); + info.PageNumber = pageIndex; + info.AnnotationType = annotation.AnnotationType.ToString(); + + Aspose.Pdf.Rectangle rect = annotation.Rect; + RectangleBounds bounds = new RectangleBounds(); + bounds.LLX = rect.LLX; + bounds.LLY = rect.LLY; + bounds.URX = rect.URX; + bounds.URY = rect.URY; + info.Bounds = bounds; + + info.Color = annotation.Color != null ? annotation.Color.ToString() : null; + info.Contents = annotation.Contents; + + MarkupAnnotation markup = annotation as MarkupAnnotation; + if (markup != null) + { + info.Title = markup.Title; + } + + annotationList.Add(info); + } + } + + JsonSerializerOptions jsonOptions = new JsonSerializerOptions(); + jsonOptions.WriteIndented = true; + + string json = JsonSerializer.Serialize(annotationList, jsonOptions); + + using (FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write)) + { + using (StreamWriter writer = new StreamWriter(fs)) + { + writer.Write(json); + } + } + } + + Console.WriteLine("Annotations exported to " + outputPath); + } +} \ No newline at end of file diff --git a/facades-annotations/export-pdf-annotations-xfdf.cs b/facades-annotations/export-pdf-annotations-xfdf.cs new file mode 100644 index 00000000..d39af7cf --- /dev/null +++ b/facades-annotations/export-pdf-annotations-xfdf.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPdf = "input.pdf"; + const string outputXfdf = "annotations.xfdf"; + + if (!File.Exists(inputPdf)) + { + Console.Error.WriteLine($"File not found: {inputPdf}"); + return; + } + + using (Document pdfDocument = new Document(inputPdf)) + { + using (FileStream xfdfStream = new FileStream(outputXfdf, FileMode.Create, FileAccess.Write)) + { + pdfDocument.ExportAnnotationsToXfdf(xfdfStream); + } + } + + Console.WriteLine($"Annotations exported to '{outputXfdf}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/export-pdf-annotations-xfdf__v2.cs b/facades-annotations/export-pdf-annotations-xfdf__v2.cs new file mode 100644 index 00000000..21b59d1a --- /dev/null +++ b/facades-annotations/export-pdf-annotations-xfdf__v2.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public static class AnnotationExporter +{ + // Exports all annotations from a PDF (provided as a byte array) to XFDF and returns the XFDF as a byte array. + public static byte[] ExportAnnotationsToXfdf(byte[] pdfBytes) + { + if (pdfBytes == null) + throw new ArgumentNullException(nameof(pdfBytes)); + + using (var pdfStream = new MemoryStream(pdfBytes)) + { + var pdfDocument = new Document(pdfStream); + using (var xfdfStream = new MemoryStream()) + { + pdfDocument.ExportAnnotationsToXfdf(xfdfStream); + // ToArray reads from the beginning of the stream, no need to reset Position. + return xfdfStream.ToArray(); + } + } + } + + // Example usage that works without external files. + public static void Main() + { + // 1. Create a simple PDF in memory. + var doc = new Document(); + doc.Pages.Add(); + var page = doc.Pages[1]; + + // 2. Add a sample text annotation (optional, demonstrates that something is exported). + var textAnnot = new TextAnnotation(page, new Rectangle(100, 700, 200, 750)) + { + Title = "Sample", + Contents = "This is a test annotation." + }; + page.Annotations.Add(textAnnot); + + // 3. Save the PDF to a byte array. + byte[] pdfBytes; + using (var ms = new MemoryStream()) + { + doc.Save(ms); + pdfBytes = ms.ToArray(); + } + + // 4. Export annotations to XFDF. + byte[] xfdfBytes = ExportAnnotationsToXfdf(pdfBytes); + + // 5. (Optional) Write the XFDF to a file for verification. + File.WriteAllBytes("annotations.xfdf", xfdfBytes); + Console.WriteLine($"Exported {xfdfBytes.Length} bytes of XFDF data."); + } +} \ No newline at end of file diff --git a/facades-annotations/extract-annotation-authors.cs b/facades-annotations/extract-annotation-authors.cs new file mode 100644 index 00000000..aa5965b1 --- /dev/null +++ b/facades-annotations/extract-annotation-authors.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("File not found: " + inputPath); + return; + } + + // Determine total number of pages in the PDF + int pageCount; + using (Document doc = new Document(inputPath)) + { + pageCount = doc.Pages.Count; + } + + // Create an array containing all possible annotation types + AnnotationType[] allTypes = (AnnotationType[])Enum.GetValues(typeof(AnnotationType)); + + // Extract annotations and group them by author (stored in Subject of MarkupAnnotation) + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + IList annotationList = editor.ExtractAnnotations(1, pageCount, allTypes); + + var authorGroups = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + foreach (Annotation annotation in annotationList) + { + // Only markup annotations have the Subject (author) property. + string author = "Unknown"; + if (annotation is MarkupAnnotation markup && !string.IsNullOrEmpty(markup.Subject)) + { + author = markup.Subject; + } + + if (!authorGroups.ContainsKey(author)) + { + authorGroups[author] = new List(); + } + authorGroups[author].Add(annotation); + } + + Console.WriteLine("Annotation author report:"); + foreach (KeyValuePair> pair in authorGroups) + { + Console.WriteLine($"Author: {pair.Key} - Count: {pair.Value.Count}"); + } + } + } +} diff --git a/facades-annotations/extract-annotation-details.cs b/facades-annotations/extract-annotation-details.cs new file mode 100644 index 00000000..1c442dff --- /dev/null +++ b/facades-annotations/extract-annotation-details.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class AnnotationInfo +{ + public string Name { get; set; } + public string Type { get; set; } + public Aspose.Pdf.Rectangle Rectangle { get; set; } + public int PageNumber { get; set; } +} + +public class Program +{ + public static void Main() + { + const string inputPath = "input.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("File not found: " + inputPath); + return; + } + + List annotations = new List(); + + using (Document doc = new Document(inputPath)) + { + int pageCount = doc.Pages.Count; + for (int i = 1; i <= pageCount; i++) + { + Page page = doc.Pages[i]; + AnnotationCollection annCollection = page.Annotations; + for (int j = 1; j <= annCollection.Count; j++) + { + Annotation annotation = annCollection[j]; + AnnotationInfo info = new AnnotationInfo(); + info.Name = annotation.Name; + info.Type = annotation.AnnotationType.ToString(); + info.Rectangle = annotation.Rect; + info.PageNumber = i; + annotations.Add(info); + } + } + } + + Console.WriteLine("Extracted annotation details:"); + foreach (AnnotationInfo info in annotations) + { + Console.WriteLine(string.Format( + "Page {0}: Name='{1}', Type={2}, Rect=[{3}, {4}, {5}, {6}]", + info.PageNumber, + info.Name ?? "(none)", + info.Type, + info.Rectangle.LLX, + info.Rectangle.LLY, + info.Rectangle.URX, + info.Rectangle.URY)); + } + } +} \ No newline at end of file diff --git a/facades-annotations/extract-annotation-rectangles.cs b/facades-annotations/extract-annotation-rectangles.cs new file mode 100644 index 00000000..ad7e9b09 --- /dev/null +++ b/facades-annotations/extract-annotation-rectangles.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Drawing; +using Aspose.Pdf.Facades; + +namespace ExtractAnnotationRectanglesExample +{ + class Program + { + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "annotations_visual.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Bind the source PDF to the annotation editor + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + Document sourceDoc = editor.Document; + int pageCount = sourceDoc.Pages.Count; + + // Define annotation types to extract (common types) + string[] annotTypes = new string[] { + "Text", "Highlight", "Square", "Circle", "Link", "FreeText", + "Line", "Stamp", "Ink", "Popup", "FileAttachment", "Sound", + "Movie", "Screen", "Widget", "PrinterMark", "Watermark", "3D", "RichMedia" + }; + + IList annotations = editor.ExtractAnnotations(1, pageCount, annotTypes); + + // Create a new PDF to hold visual pages + using (Document outDoc = new Document()) + { + foreach (Annotation ann in annotations) + { + // Get the rectangle of the annotation (in page coordinates) + Aspose.Pdf.Rectangle annRect = ann.Rect; + + // Create a new blank page (size 600x800 points) + Page page = outDoc.Pages.Add(); + page.PageInfo.Width = 600; + page.PageInfo.Height = 800; + + // Draw the annotation rectangle on the page using a Graph container + Graph graph = new Graph(600.0, 800.0); // double literals as required by the new constructor + var shape = new Aspose.Pdf.Drawing.Rectangle( + (float)annRect.LLX, + (float)annRect.LLY, + (float)(annRect.URX - annRect.LLX), + (float)(annRect.URY - annRect.LLY)); + shape.GraphInfo = new GraphInfo + { + Color = Aspose.Pdf.Color.Red, + LineWidth = 2f // float literal + }; + graph.Shapes.Add(shape); + page.Paragraphs.Add(graph); + } + + outDoc.Save(outputPath); + } + } + + Console.WriteLine($"Annotation rectangles visualized in '{outputPath}'."); + } + } +} diff --git a/facades-annotations/extract-annotation-summary.cs b/facades-annotations/extract-annotation-summary.cs new file mode 100644 index 00000000..8ef072d4 --- /dev/null +++ b/facades-annotations/extract-annotation-summary.cs @@ -0,0 +1,53 @@ +using System; +using System.IO; +using System.Text; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Text; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "summary.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Collect annotation comments + StringBuilder sb = new StringBuilder(); + + using (Document sourceDoc = new Document(inputPath)) + { + for (int pageIndex = 1; pageIndex <= sourceDoc.Pages.Count; pageIndex++) + { + Page page = sourceDoc.Pages[pageIndex]; + for (int annIndex = 1; annIndex <= page.Annotations.Count; annIndex++) + { + Annotation annotation = page.Annotations[annIndex]; + if (!string.IsNullOrEmpty(annotation.Contents)) + { + sb.AppendLine($"Page {pageIndex}, Annotation {annIndex}: {annotation.Contents}"); + } + } + } + } + + // Create summary PDF + using (Document summaryDoc = new Document()) + { + Page summaryPage = summaryDoc.Pages.Add(); + TextFragment tf = new TextFragment(sb.ToString()); + tf.TextState.FontSize = 12; + tf.TextState.Font = FontRepository.FindFont("Helvetica"); + summaryPage.Paragraphs.Add(tf); + summaryDoc.Save(outputPath); + } + + Console.WriteLine($"Summary PDF saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-annotations-first-five-pages.cs b/facades-annotations/flatten-annotations-first-five-pages.cs new file mode 100644 index 00000000..110e75e8 --- /dev/null +++ b/facades-annotations/flatten-annotations-first-five-pages.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened_output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Initialize the annotation editor and bind the PDF file + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + + // Retrieve all possible annotation types + AnnotationType[] allTypes = (AnnotationType[])Enum.GetValues(typeof(AnnotationType)); + + // Flatten annotations on pages 1 through 5 (inclusive) + editor.FlatteningAnnotations(1, 5, allTypes); + + // Save the modified document + editor.Save(outputPath); + editor.Close(); + + Console.WriteLine($"Annotations on first five pages flattened and saved to '{outputPath}'."); + } +} diff --git a/facades-annotations/flatten-annotations-log-sizes.cs b/facades-annotations/flatten-annotations-log-sizes.cs new file mode 100644 index 00000000..cd8623f3 --- /dev/null +++ b/facades-annotations/flatten-annotations-log-sizes.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened_output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + long originalSize = new FileInfo(inputPath).Length; + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.FlatteningAnnotations(); + editor.Save(outputPath); + editor.Close(); + } + + long newSize = new FileInfo(outputPath).Length; + + Console.WriteLine("Original file size: " + originalSize + " bytes"); + Console.WriteLine("Flattened file size: " + newSize + " bytes"); + } +} diff --git a/facades-annotations/flatten-annotations-verify.cs b/facades-annotations/flatten-annotations-verify.cs new file mode 100644 index 00000000..0313277a --- /dev/null +++ b/facades-annotations/flatten-annotations-verify.cs @@ -0,0 +1,47 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + // Flatten all annotations in the document + doc.Flatten(); + + // Scan each page to verify that no annotations remain + bool anyAnnotations = false; + for (int i = 1; i <= doc.Pages.Count; i++) + { + Page page = doc.Pages[i]; + if (page.Annotations.Count > 0) + { + anyAnnotations = true; + Console.WriteLine($"Page {i} still has {page.Annotations.Count} annotation(s)."); + } + } + + if (!anyAnnotations) + { + Console.WriteLine("All annotations successfully flattened."); + } + + // Save the flattened PDF + doc.Save(outputPath); + } + + Console.WriteLine($"Flattened PDF saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-pdf-add-metadata.cs b/facades-annotations/flatten-pdf-add-metadata.cs new file mode 100644 index 00000000..fb52e006 --- /dev/null +++ b/facades-annotations/flatten-pdf-add-metadata.cs @@ -0,0 +1,32 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + // Flatten all form fields and annotations + doc.Flatten(); + + // Record the flattening date in the document metadata (ModDate) + doc.Info.ModDate = DateTime.Now; + + // Save the flattened PDF + doc.Save(outputPath); + } + + Console.WriteLine($"Flattened PDF saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-pdf-annotations-nightly.cs b/facades-annotations/flatten-pdf-annotations-nightly.cs new file mode 100644 index 00000000..306a37e6 --- /dev/null +++ b/facades-annotations/flatten-pdf-annotations-nightly.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using System.Diagnostics; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main(string[] args) + { + string taskName = "FlattenPDFAnnotationsNightly"; + string sharePath = @"\\server\share\pdfs"; + + if (args != null && args.Length > 0 && args[0] == "install") + { + InstallScheduledTask(taskName, sharePath); + Console.WriteLine("Scheduled task installed."); + return; + } + + FlattenAnnotationsInFolder(sharePath); + } + + private static void InstallScheduledTask(string taskName, string sharePath) + { + string exePath = Process.GetCurrentProcess().MainModule.FileName; + string arguments = $"\"{exePath}\""; + // Schedule daily at 02:00 AM + string scheduleCommand = $"/Create /SC DAILY /TN \"{taskName}\" /TR \"{arguments}\" /ST 02:00 /F"; + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = "schtasks", + Arguments = scheduleCommand, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + using (Process process = Process.Start(startInfo)) + { + process.WaitForExit(); + } + } + + private static void FlattenAnnotationsInFolder(string folderPath) + { + if (!Directory.Exists(folderPath)) + { + Console.Error.WriteLine("Folder does not exist: " + folderPath); + return; + } + + string[] pdfFiles = Directory.GetFiles(folderPath, "*.pdf", SearchOption.TopDirectoryOnly); + foreach (string pdfFilePath in pdfFiles) + { + string directory = Path.GetDirectoryName(pdfFilePath); + string fileName = Path.GetFileName(pdfFilePath); + + string originalDirectory = Directory.GetCurrentDirectory(); + Directory.SetCurrentDirectory(directory); + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(fileName); + editor.FlatteningAnnotations(); + editor.Save(fileName); + } + + Directory.SetCurrentDirectory(originalDirectory); + Console.WriteLine("Flattened: " + fileName); + } + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-pdf-annotations.cs b/facades-annotations/flatten-pdf-annotations.cs new file mode 100644 index 00000000..d597861b --- /dev/null +++ b/facades-annotations/flatten-pdf-annotations.cs @@ -0,0 +1,28 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.FlatteningAnnotations(); + editor.Save(outputPath); + } + + Console.WriteLine($"Annotations flattened and saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-pdf-annotations__v2.cs b/facades-annotations/flatten-pdf-annotations__v2.cs new file mode 100644 index 00000000..18f01575 --- /dev/null +++ b/facades-annotations/flatten-pdf-annotations__v2.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string folderPath = "pdfs"; + + if (!Directory.Exists(folderPath)) + { + Console.Error.WriteLine($"Folder not found: {folderPath}"); + return; + } + + // Change the current working directory to the target folder so that Save uses simple filenames. + Directory.SetCurrentDirectory(folderPath); + + string[] pdfFiles = Directory.GetFiles(".", "*.pdf"); + + foreach (string pdfFile in pdfFiles) + { + string fileNameWithoutExt = Path.GetFileNameWithoutExtension(pdfFile); + string outputFileName = $"{fileNameWithoutExt}_flattened.pdf"; + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(pdfFile); + editor.FlatteningAnnotations(); + editor.Save(outputFileName); + editor.Close(); + } + + Console.WriteLine($"Flattened: {outputFileName}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-pdf-annotations__v3.cs b/facades-annotations/flatten-pdf-annotations__v3.cs new file mode 100644 index 00000000..1511f645 --- /dev/null +++ b/facades-annotations/flatten-pdf-annotations__v3.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + // Record original file size + FileInfo originalInfo = new FileInfo(inputPath); + long originalSize = originalInfo.Length; + + using (Document doc = new Document(inputPath)) + { + // Flatten all annotations (and form fields) into the page content + doc.Flatten(); + + // Save the flattened document + doc.Save(outputPath); + } + + // Record new file size after flattening + FileInfo newInfo = new FileInfo(outputPath); + long newSize = newInfo.Length; + + long reduction = originalSize - newSize; + double reductionPercent = originalSize > 0 ? (double)reduction / originalSize * 100 : 0; + + Console.WriteLine($"Original size: {originalSize} bytes"); + Console.WriteLine($"Flattened size: {newSize} bytes"); + Console.WriteLine($"Size reduction: {reduction} bytes ({reductionPercent:F2}%)"); + } +} diff --git a/facades-annotations/flatten-pdf-annotations__v4.cs b/facades-annotations/flatten-pdf-annotations__v4.cs new file mode 100644 index 00000000..88789454 --- /dev/null +++ b/facades-annotations/flatten-pdf-annotations__v4.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +namespace PdfUtilities +{ + public class PdfAnnotationFlattener + { + public static MemoryStream FlattenAnnotations(Stream inputPdfStream) + { + if (inputPdfStream == null) + throw new ArgumentNullException(nameof(inputPdfStream)); + + var outputStream = new MemoryStream(); + using (var editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPdfStream); + editor.FlatteningAnnotations(); + editor.Save(outputStream); + } + outputStream.Position = 0; + return outputStream; + } + } + + // Entry point required when the project is built as an executable. + internal class Program + { + static void Main(string[] args) + { + // Placeholder – no runtime logic required for the library. + // Example usage (commented out): + // using var input = File.OpenRead("input.pdf"); + // var result = PdfAnnotationFlattener.FlattenAnnotations(input); + // File.WriteAllBytes("output.pdf", result.ToArray()); + } + } +} \ No newline at end of file diff --git a/facades-annotations/flatten-pdf-custom-output.cs b/facades-annotations/flatten-pdf-custom-output.cs new file mode 100644 index 00000000..3fc41342 --- /dev/null +++ b/facades-annotations/flatten-pdf-custom-output.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputDirectory = "flattened"; + const string outputFileName = "flattened_output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + try + { + // Ensure the output directory exists + DirectoryInfo outputDirInfo = new DirectoryInfo(outputDirectory); + if (!outputDirInfo.Exists) + { + outputDirInfo.Create(); + } + + // Switch the current working directory to the output directory + string previousDir = Environment.CurrentDirectory; + Environment.CurrentDirectory = outputDirInfo.FullName; + + using (Document doc = new Document(inputPath)) + { + // Flatten the PDF (remove form fields and annotations) + doc.Flatten(); + + // Save using a simple filename (no directory path as per style rule) + doc.Save(outputFileName); + } + + // Restore the original working directory (optional) + Environment.CurrentDirectory = previousDir; + + Console.WriteLine($"Flattened PDF saved to '{Path.Combine(outputDirInfo.FullName, outputFileName)}'"); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/folder-monitor-flatten-pdf-annotations.cs b/facades-annotations/folder-monitor-flatten-pdf-annotations.cs new file mode 100644 index 00000000..bd05d85c --- /dev/null +++ b/facades-annotations/folder-monitor-flatten-pdf-annotations.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +namespace PdfAnnotationFlattenerService +{ + class Program + { + private const string WatchFolder = "input"; + private const string Filter = "*.pdf"; + + static void Main() + { + if (!Directory.Exists(WatchFolder)) + { + Console.Error.WriteLine($"Watch folder does not exist: {WatchFolder}"); + return; + } + + FileSystemWatcher watcher = new FileSystemWatcher(); + watcher.Path = WatchFolder; + watcher.Filter = Filter; + watcher.Created += OnCreated; + watcher.EnableRaisingEvents = true; + + Console.WriteLine($"Monitoring folder '{WatchFolder}' for new PDF files. Press Enter to exit."); + Console.ReadLine(); + } + + private static void OnCreated(object sender, FileSystemEventArgs e) + { + // Small delay to ensure the file is fully written + System.Threading.Thread.Sleep(500); + try + { + ProcessPdf(e.FullPath); + Console.WriteLine($"Processed and flattened: {e.Name}"); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error processing '{e.Name}': {ex.Message}"); + } + } + + private static void ProcessPdf(string inputPath) + { + // Ensure the file exists and has .pdf extension + if (!File.Exists(inputPath)) + { + throw new FileNotFoundException("Input PDF not found.", inputPath); + } + + string outputFileName = Path.GetFileNameWithoutExtension(inputPath) + "_flattened.pdf"; + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(inputPath); + editor.FlatteningAnnotations(); + editor.Save(outputFileName); + } + } + } +} diff --git a/facades-annotations/get-annotation-names-by-author.cs b/facades-annotations/get-annotation-names-by-author.cs new file mode 100644 index 00000000..4c8f62f7 --- /dev/null +++ b/facades-annotations/get-annotation-names-by-author.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class AnnotationHelper +{ + /// + /// Returns the list of annotation names whose author (stored in the Subject property) matches the specified author string. + /// + /// Path to the input PDF file. + /// Author name to filter annotations. + /// List of annotation names. + public static List GetAnnotationNamesByAuthor(string pdfPath, string author) + { + if (string.IsNullOrEmpty(pdfPath)) + throw new ArgumentException("PDF path must be provided.", nameof(pdfPath)); + + if (!File.Exists(pdfPath)) + throw new FileNotFoundException("PDF file not found.", pdfPath); + + var matchingNames = new List(); + + using (Document doc = new Document(pdfPath)) + { + // Iterate through all pages + foreach (Page page in doc.Pages) + { + // Iterate through all annotations on the current page + foreach (Annotation annotation in page.Annotations) + { + // Only markup annotations expose the Subject property (used here to store the author) + if (annotation is MarkupAnnotation markup && + string.Equals(markup.Subject, author, StringComparison.OrdinalIgnoreCase)) + { + if (!string.IsNullOrEmpty(annotation.Name)) + matchingNames.Add(annotation.Name); + } + } + } + } + + return matchingNames; + } + + // --------------------------------------------------------------------- + // Helper: creates a minimal PDF with a single text annotation if the + // specified file does not exist. This allows the sample to run without + // requiring an external PDF. + // --------------------------------------------------------------------- + private static void EnsureSamplePdf(string path, string author) + { + if (File.Exists(path)) + return; + + // Create a one‑page document + var doc = new Document(); + var page = doc.Pages.Add(); + + // Add a simple text annotation and store the author in the Subject field + var textAnnot = new TextAnnotation(page, new Aspose.Pdf.Rectangle(100, 600, 300, 650)) + { + Name = "SampleAnnotation", + Subject = author, // author information + Title = "Demo", + Contents = "This is a demo annotation." + }; + page.Annotations.Add(textAnnot); + + doc.Save(path); + } + + // Example usage + public static void Main() + { + const string inputPdf = "sample.pdf"; + const string targetAuthor = "John Doe"; + + // Ensure a PDF exists so the demo does not throw FileNotFoundException + EnsureSamplePdf(inputPdf, targetAuthor); + + List names; + try + { + names = GetAnnotationNamesByAuthor(inputPdf, targetAuthor); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + return; + } + + Console.WriteLine($"Annotations authored by '{targetAuthor}':"); + if (names.Count == 0) + { + Console.WriteLine(" (none found)"); + } + else + { + foreach (string name in names) + { + Console.WriteLine($" {name}"); + } + } + } +} diff --git a/facades-annotations/import-annotations-no-overwrite.cs b/facades-annotations/import-annotations-no-overwrite.cs new file mode 100644 index 00000000..065d3a06 --- /dev/null +++ b/facades-annotations/import-annotations-no-overwrite.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; // needed for AnnotationType enum + +class Program +{ + static void Main() + { + const string targetPath = "target.pdf"; + const string outputPath = "merged_annotations.pdf"; + string[] sourcePaths = new string[] { "source1.pdf", "source2.pdf" }; + + if (!File.Exists(targetPath)) + { + Console.Error.WriteLine($"Target file not found: {targetPath}"); + return; + } + + using (Document targetDoc = new Document(targetPath)) + { + using (PdfAnnotationEditor editor = new PdfAnnotationEditor(targetDoc)) + { + // Import annotations from the source PDFs without overwriting existing ones. + // The current Aspose.Pdf API overload expects an array of AnnotationType. + // Passing null imports all annotation types and, by design, does not overwrite + // annotations that already exist in the target document. + editor.ImportAnnotations(sourcePaths, null); + + // Save the document with merged annotations + targetDoc.Save(outputPath); + } + } + + Console.WriteLine($"Annotations imported successfully. Output saved to '{outputPath}'."); + } +} diff --git a/facades-annotations/import-annotations-xfdf.cs b/facades-annotations/import-annotations-xfdf.cs new file mode 100644 index 00000000..5d9c3aee --- /dev/null +++ b/facades-annotations/import-annotations-xfdf.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPdf = "input.pdf"; + const string xfdfFile = "annotations.xfdf"; + const string outputPdf = "output.pdf"; + + if (!File.Exists(inputPdf)) + { + Console.Error.WriteLine($"Input PDF not found: {inputPdf}"); + return; + } + + if (!File.Exists(xfdfFile)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfFile}"); + return; + } + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + try + { + editor.BindPdf(inputPdf); + editor.ImportAnnotationsFromXfdf(xfdfFile); + editor.Save(outputPdf); + } + finally + { + editor.Close(); + } + + Console.WriteLine($"Annotations imported and saved to '{outputPdf}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/import-xfdf-and-cleanup.cs b/facades-annotations/import-xfdf-and-cleanup.cs new file mode 100644 index 00000000..0a587fcb --- /dev/null +++ b/facades-annotations/import-xfdf-and-cleanup.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string inputPdfPath = "input.pdf"; + const string xfdfTempPath = "temp.xfdf"; + const string outputPdfPath = "output.pdf"; + + if (!File.Exists(inputPdfPath)) + { + Console.Error.WriteLine($"Input PDF not found: {inputPdfPath}"); + return; + } + + if (!File.Exists(xfdfTempPath)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfTempPath}"); + return; + } + + try + { + using (Document pdfDoc = new Document(inputPdfPath)) + { + // Import annotations from the XFDF file + pdfDoc.ImportAnnotationsFromXfdf(xfdfTempPath); + // Save the updated PDF + pdfDoc.Save(outputPdfPath); + } + + // Delete the temporary XFDF file after successful import and save + File.Delete(xfdfTempPath); + Console.WriteLine($"Temporary XFDF file deleted: {xfdfTempPath}"); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} diff --git a/facades-annotations/import-xfdf-annotations.cs b/facades-annotations/import-xfdf-annotations.cs new file mode 100644 index 00000000..896ad9b5 --- /dev/null +++ b/facades-annotations/import-xfdf-annotations.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPdfPath = "input.pdf"; + const string xfdfPath = "annotations.xfdf"; + const string outputPdfPath = "output.pdf"; + const int startPage = 2; // inclusive, 1‑based + const int endPage = 4; // inclusive, 1‑based + + if (!File.Exists(inputPdfPath)) + { + Console.Error.WriteLine($"PDF file not found: {inputPdfPath}"); + return; + } + if (!File.Exists(xfdfPath)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfPath}"); + return; + } + + // Load the target PDF document. + using (Document targetDoc = new Document(inputPdfPath)) + { + // Load XFDF annotations into a temporary PDF document. + Document xfdfDoc = new Document(); + using (FileStream xfdfStream = File.OpenRead(xfdfPath)) + { + XfdfReader.ReadAnnotations(xfdfStream, xfdfDoc); + } + + // Ensure the target document has enough pages for the requested range. + while (targetDoc.Pages.Count < endPage) + { + targetDoc.Pages.Add(); + } + + // Import annotations from the specified page range of the XFDF document. + for (int pageIndex = startPage; pageIndex <= endPage && pageIndex <= xfdfDoc.Pages.Count; pageIndex++) + { + Page sourcePage = xfdfDoc.Pages[pageIndex]; + Page destinationPage = targetDoc.Pages[pageIndex]; + + foreach (Annotation sourceAnnotation in sourcePage.Annotations) + { + // Clone the annotation to avoid reference issues. + Annotation clonedAnnotation = (Annotation)sourceAnnotation.Clone(); + destinationPage.Annotations.Add(clonedAnnotation); + } + } + + // Save the updated PDF. + targetDoc.Save(outputPdfPath); + Console.WriteLine($"Annotations imported to pages {startPage}-{endPage} and saved as '{outputPdfPath}'."); + } + } +} \ No newline at end of file diff --git a/facades-annotations/import-xfdf-annotations__v2.cs b/facades-annotations/import-xfdf-annotations__v2.cs new file mode 100644 index 00000000..fcd80268 --- /dev/null +++ b/facades-annotations/import-xfdf-annotations__v2.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string pdfPath = "input.pdf"; + const string xfdfPath = "annotations.xfdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(pdfPath)) + { + Console.Error.WriteLine($"PDF file not found: {pdfPath}"); + return; + } + + if (!File.Exists(xfdfPath)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfPath}"); + return; + } + + using (FileStream pdfStream = new FileStream(pdfPath, FileMode.Open, FileAccess.Read)) + using (Document pdfDoc = new Document(pdfStream)) + using (FileStream xfdfStream = new FileStream(xfdfPath, FileMode.Open, FileAccess.Read)) + { + pdfDoc.ImportAnnotationsFromXfdf(xfdfStream); + pdfDoc.Save(outputPath); + } + + Console.WriteLine($"Annotations imported and saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/import-xfdf-into-multiple-pdfs.cs b/facades-annotations/import-xfdf-into-multiple-pdfs.cs new file mode 100644 index 00000000..a818c221 --- /dev/null +++ b/facades-annotations/import-xfdf-into-multiple-pdfs.cs @@ -0,0 +1,41 @@ +using System; +using System.IO; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + // List of PDF files to which the same XFDF comments will be applied + string[] inputFiles = new string[] { "doc1.pdf", "doc2.pdf", "doc3.pdf" }; + string xfdfFile = "comments.xfdf"; + + if (!File.Exists(xfdfFile)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfFile}"); + return; + } + + foreach (string inputPath in inputFiles) + { + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input PDF not found: {inputPath}"); + continue; + } + + using (Document pdfDoc = new Document(inputPath)) + { + // Import all annotations (comments) from the XFDF file + pdfDoc.ImportAnnotationsFromXfdf(xfdfFile); + + // Create a simple output filename – same name with suffix + string outputFileName = Path.GetFileNameWithoutExtension(inputPath) + "_annotated.pdf"; + outputFileName = Path.GetFileName(outputFileName); // ensure no directory part + + pdfDoc.Save(outputFileName); + Console.WriteLine($"Annotated PDF saved as '{outputFileName}'."); + } + } + } +} \ No newline at end of file diff --git a/facades-annotations/index.json b/facades-annotations/index.json new file mode 100644 index 00000000..b0f8ec8c --- /dev/null +++ b/facades-annotations/index.json @@ -0,0 +1,2246 @@ +{ + "category": "Facades - Annotations", + "last_updated": "2026-03-26T19:20:39Z", + "examples": { + "delete-all-annotations": { + "title": "Delete All Annotations from PDF using PdfAnnotationEditor", + "filename": "delete-all-annotations.cs", + "description": "Demonstrates how to bind a PDF to PdfAnnotationEditor, remove all annotations, and save the cleaned document.", + "tags": [ + "annotations", + "pdf", + "facade", + "delete", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:23:00Z", + "status": "verified" + }, + "delete-pdf-annotations": { + "title": "Delete All Annotations from PDFs in a Folder", + "filename": "delete-pdf-annotations.cs", + "description": "Iterates through a specified folder, removes all annotations from each PDF using PdfAnnotationEditor, and overwrites the original files.", + "tags": [ + "annotations", + "pdf", + "batch", + "delete", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:23:10Z", + "status": "verified" + }, + "delete-text-annotations": { + "title": "Delete Text Annotations from PDF", + "filename": "delete-text-annotations.cs", + "description": "Demonstrates how to remove only text annotations from a PDF using PdfAnnotationEditor.", + "tags": [ + "annotations", + "delete", + "pdf", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:23:19Z", + "status": "verified" + }, + "remove-link-annotations": { + "title": "Remove Link Annotations from Specific Pages", + "filename": "remove-link-annotations.cs", + "description": "Demonstrates how to delete link annotations on pages 3 through 7 using PdfAnnotationEditor.", + "tags": [ + "annotations", + "link", + "pdf", + "Aspose.Pdf", + "delete" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExtractAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotation", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:23:33Z", + "status": "verified" + }, + "delete-annotation-by-name": { + "title": "Delete Annotation by Name from PDF", + "filename": "delete-annotation-by-name.cs", + "description": "Demonstrates how to delete a single PDF annotation identified by its name using PdfAnnotationEditor.", + "tags": [ + "annotation", + "delete", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotation", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:24:05Z", + "status": "verified" + }, + "delete-annotation-by-name__v2": { + "title": "Delete Annotation by Name using PdfAnnotationEditor", + "filename": "delete-annotation-by-name__v2.cs", + "description": "Demonstrates how to delete a specific annotation from a PDF by its name using the PdfAnnotationEditor class.", + "tags": [ + "annotation", + "delete", + "pdf", + "aspose-pdf", + "facades" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotation", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:24:21Z", + "status": "verified" + }, + "export-pdf-annotations-xfdf": { + "title": "Export PDF Annotations to XFDF File", + "filename": "export-pdf-annotations-xfdf.cs", + "description": "Demonstrates how to export all annotations from a PDF document to an XFDF file using a stream.", + "tags": [ + "annotations", + "xfdf", + "export", + "pdf", + "stream" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ExportAnnotationsToXfdf" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:24:32Z", + "status": "verified" + }, + "export-annotations-xfdf": { + "title": "Export Annotations from Specific Pages to XFDF Stream", + "filename": "export-annotations-xfdf.cs", + "description": "Exports annotations from the first two pages of a PDF into an in‑memory XFDF stream using PdfAnnotationEditor.", + "tags": [ + "annotations", + "xfdf", + "export", + "memory-stream", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ExportAnnotationsXfdf", + "Document", + "MemoryStream" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:24:49Z", + "status": "verified" + }, + "export-highlight-annotations": { + "title": "Export Highlight Annotations to XFDF", + "filename": "export-highlight-annotations.cs", + "description": "Exports only highlight annotations from a PDF to an XFDF file using PdfAnnotationEditor.", + "tags": [ + "annotations", + "xfdf", + "export", + "highlight", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExportAnnotationsXfdf", + "Aspose.Pdf.Document.Pages.Count" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:25:00Z", + "status": "verified" + }, + "import-annotations-xfdf": { + "title": "Import Annotations from XFDF into PDF", + "filename": "import-annotations-xfdf.cs", + "description": "Demonstrates how to import all annotations from an XFDF file into an existing PDF using PdfAnnotationEditor.", + "tags": [ + "annotations", + "xfdf", + "import", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Close" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:25:16Z", + "status": "verified" + }, + "import-xfdf-annotations": { + "title": "Import XFDF Annotations onto Specific Pages", + "filename": "import-xfdf-annotations.cs", + "description": "Demonstrates exporting annotations from a page range to XFDF and then importing them into another PDF.", + "tags": [ + "xfdf", + "annotations", + "import", + "export", + "pages" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExportAnnotationsXfdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Close" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:26:42Z", + "status": "verified" + }, + "import-annotations-no-overwrite": { + "title": "Import Annotations Without Overwriting Existing Ones", + "filename": "import-annotations-no-overwrite.cs", + "description": "Demonstrates how to import annotations from other PDFs while preserving existing annotations by disabling the overwrite option.", + "tags": [ + "annotations", + "import", + "pdf", + "facades", + "aspnet" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.OverwriteAnnotations", + "PdfAnnotationEditor.ImportAnnotations", + "Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:27:05Z", + "status": "verified" + }, + "flatten-pdf-annotations": { + "title": "Flatten All Annotations in a PDF", + "filename": "flatten-pdf-annotations.cs", + "description": "Loads a PDF, flattens all its annotations into non‑editable visual content, and saves the result.", + "tags": [ + "flatten", + "annotations", + "pdf", + "aspose-pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:27:17Z", + "status": "verified" + }, + "flatten-annotations-first-five-pages": { + "title": "Flatten Annotations on First Five Pages", + "filename": "flatten-annotations-first-five-pages.cs", + "description": "Flattens all annotations on the first five pages of a PDF using PdfAnnotationEditor with a page range argument.", + "tags": [ + "flatten", + "annotations", + "pdf", + "facade" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:27:31Z", + "status": "verified" + }, + "modify-annotation-author": { + "title": "Modify Annotation Author on Specific Page", + "filename": "modify-annotation-author.cs", + "description": "Demonstrates how to change the author of annotations on page three using PdfAnnotationEditor.", + "tags": [ + "annotations", + "author", + "pdf", + "Aspose.Pdf", + "facades" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ModifyAnnotationsAuthor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:27:46Z", + "status": "verified" + }, + "modify-annotation-subject-color": { + "title": "Modify Annotation Subject and Color in PDF", + "filename": "modify-annotation-subject-color.cs", + "description": "Demonstrates how to change the subject and color of existing annotations using PdfAnnotationEditor.ModifyAnnotations.", + "tags": [ + "annotation", + "modify", + "color", + "subject", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ModifyAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Close" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:28:17Z", + "status": "verified" + }, + "set-annotations-open": { + "title": "Set All Annotations to Open in a PDF", + "filename": "set-annotations-open.cs", + "description": "Iterates through all pages and annotations in a PDF and sets the Open flag to true, then saves the modified document.", + "tags": [ + "annotations", + "open", + "pdf", + "iteration" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Page.Annotations", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:29:15Z", + "status": "verified" + }, + "update-annotation-modified-date": { + "title": "Update Annotation Modified Date Using PdfAnnotationEditor", + "filename": "update-annotation-modified-date.cs", + "description": "Demonstrates how to set the Modified property of a PDF annotation to the current system time using PdfAnnotationEditor.ModifyAnnotations.", + "tags": [ + "annotation", + "modify", + "pdf", + "datetime", + "facade" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ModifyAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Annotations.Annotation.Modified" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:29:50Z", + "status": "verified" + }, + "set-readonly-annotation": { + "title": "Set ReadOnly Flag on PDF Annotation", + "filename": "set-readonly-annotation.cs", + "description": "Demonstrates how to apply the ReadOnly flag to a specific annotation using PdfAnnotationEditor.", + "tags": [ + "annotation", + "readonly", + "modify", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ModifyAnnotations", + "PdfAnnotationEditor.Save", + "DocumentPrivilege.ModifyAnnotations", + "AnnotationFlags", + "TextAnnotation" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:30:41Z", + "status": "verified" + }, + "batch-update-annotation-author": { + "title": "Batch Update Annotation Author in PDFs", + "filename": "batch-update-annotation-author.cs", + "description": "Loops through PDF files in a folder and changes the author of all annotations from a specified source author to a new author using PdfAnnotationEditor.", + "tags": [ + "annotations", + "batch", + "author", + "pdf", + "facade" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ModifyAnnotationsAuthor", + "PdfAnnotationEditor.Save", + "Document.Pages.Count" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:30:54Z", + "status": "verified" + }, + "export-pdf-annotations-xfdf__v2": { + "title": "Export PDF Annotations to XFDF Using MemoryStream", + "filename": "export-pdf-annotations-xfdf__v2.cs", + "description": "Demonstrates how to load a PDF from a byte array via MemoryStream, export its annotations to XFDF using Aspose.Pdf, and return the XFDF as a byte array.", + "tags": [ + "annotations", + "xfdf", + "memorystream", + "pdf", + "export" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ExportAnnotationsToXfdf" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:31:19Z", + "status": "verified" + }, + "import-xfdf-annotations__v2": { + "title": "Import XFDF Annotations into PDF from Streams", + "filename": "import-xfdf-annotations__v2.cs", + "description": "Demonstrates loading a PDF and an XFDF file from streams and importing the XFDF annotations into the PDF without using temporary files.", + "tags": [ + "xfdf", + "annotations", + "stream", + "import", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:31:30Z", + "status": "verified" + }, + "delete-flatten-annotations": { + "title": "Delete and Flatten Annotations in PDF", + "filename": "delete-flatten-annotations.cs", + "description": "Deletes all annotations from a PDF, flattens any remaining ones, and saves the result.", + "tags": [ + "annotations", + "flatten", + "pdf", + "aspdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:32:51Z", + "status": "verified" + }, + "validate-xfdf": { + "title": "Validate XFDF File Against Schema", + "filename": "validate-xfdf.cs", + "description": "Loads an exported XFDF file, validates it against the XFDF XSD schema, and reports any validation errors.", + "tags": [ + "xfdf", + "validation", + "xml", + "schema", + "aspdf" + ], + "apis_used": [ + "System.Xml.XmlReader", + "System.Xml.XmlReaderSettings", + "System.Xml.Schema.XmlSchemaSet", + "System.Xml.Schema.ValidationEventHandler" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:33:21Z", + "status": "verified" + }, + "compare-annotation-counts": { + "title": "Compare Annotation Counts Before and After Deletion", + "filename": "compare-annotation-counts.cs", + "description": "Loads a PDF, reports the number of annotations, deletes all annotations using PdfAnnotationEditor, then reports the remaining count.", + "tags": [ + "annotations", + "delete", + "pdf", + "aspnet", + "comparison" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Facades.PdfAnnotationEditor" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:33:44Z", + "status": "verified" + }, + "extract-annotation-details": { + "title": "Extract Annotation Details from PDF", + "filename": "extract-annotation-details.cs", + "description": "Loads a PDF, iterates all pages and annotations, and extracts each annotation's name, type, rectangle and page number into a custom C# object.", + "tags": [ + "annotation", + "pdf", + "extraction", + "aspnet", + "metadata" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.AnnotationCollection" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:34:02Z", + "status": "verified" + }, + "export-pdf-annotations-json": { + "title": "Export PDF Annotations to JSON Log", + "filename": "export-pdf-annotations-json.cs", + "description": "Extracts annotation properties from a PDF and writes them as a JSON file for auditing purposes.", + "tags": [ + "annotations", + "json", + "export", + "audit", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.MarkupAnnotation", + "System.Text.Json.JsonSerializer", + "System.IO.FileStream" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:34:29Z", + "status": "verified" + }, + "delete-annotation-error-handling": { + "title": "Delete Annotation with Error Handling", + "filename": "delete-annotation-error-handling.cs", + "description": "Demonstrates how to delete an annotation by name and gracefully handle the case when the annotation does not exist.", + "tags": [ + "annotation", + "error-handling", + "pdf", + "facade" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotation", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:34:47Z", + "status": "verified" + }, + "delete-annotations-by-author": { + "title": "Delete PDF Annotations by Author", + "filename": "delete-annotations-by-author.cs", + "description": "Demonstrates how to remove annotations from a PDF whose author matches a specified name.", + "tags": [ + "annotations", + "delete", + "author", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.AnnotationCollection.Delete", + "Aspose.Pdf.Annotations.Annotation.Author" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:35:26Z", + "status": "verified" + }, + "delete-annotations-by-color": { + "title": "Delete Annotations by Color in PDF", + "filename": "delete-annotations-by-color.cs", + "description": "Demonstrates how to remove only those annotations whose color matches a specific RGB value.", + "tags": [ + "annotations", + "color", + "delete", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.AnnotationCollection.Delete", + "Aspose.Pdf.Annotations.Annotation.Color", + "Aspose.Pdf.Color.FromRgb" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:35:50Z", + "status": "verified" + }, + "export-import-annotations-xfdf": { + "title": "Export and Import PDF Annotations via XFDF", + "filename": "export-import-annotations-xfdf.cs", + "description": "Demonstrates exporting all annotations from a PDF to an XFDF file and then importing them into another PDF to duplicate the annotation layout.", + "tags": [ + "annotations", + "xfdf", + "export", + "import", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document.ExportAnnotationsToXfdf", + "Aspose.Pdf.Document.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:36:04Z", + "status": "verified" + }, + "flatten-pdf-annotations__v2": { + "title": "Flatten Annotations in PDFs in a Folder", + "filename": "flatten-pdf-annotations__v2.cs", + "description": "Processes all PDF files in a specified folder, flattens their annotations, and saves new files with a \"_flattened\" suffix.", + "tags": [ + "pdf", + "annotations", + "flatten", + "batch", + "aspose-pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:36:22Z", + "status": "verified" + }, + "batch-delete-stamp-annotations": { + "title": "Batch Delete Stamp Annotations from PDFs", + "filename": "batch-delete-stamp-annotations.cs", + "description": "Iterates over all PDF files in a folder and removes stamp annotations using PdfAnnotationEditor.", + "tags": [ + "pdf", + "annotations", + "batch", + "delete", + "aspdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:36:41Z", + "status": "verified" + }, + "import-xfdf-into-multiple-pdfs": { + "title": "Import XFDF Comments into Multiple PDFs", + "filename": "import-xfdf-into-multiple-pdfs.cs", + "description": "Demonstrates loading several PDF files, importing a shared XFDF comment file into each, and saving the annotated PDFs.", + "tags": [ + "xfdf", + "annotations", + "pdf", + "batch", + "import" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:36:55Z", + "status": "verified" + }, + "delete-annotations-parallel": { + "title": "Delete All Annotations from Multiple PDFs in Parallel", + "filename": "delete-annotations-parallel.cs", + "description": "Demonstrates how to use Parallel.ForEach with Aspose.Pdf to delete all annotations from a batch of PDF files concurrently.", + "tags": [ + "annotations", + "parallel", + "pdf", + "batch", + "aspose-pdf" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save", + "Parallel.ForEach" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:37:23Z", + "status": "verified" + }, + "measure-flatten-annotations": { + "title": "Measure Annotation Flattening Time on PDF", + "filename": "measure-flatten-annotations.cs", + "description": "Loads a 500‑page PDF, flattens all annotations while timing the operation, and saves the flattened result.", + "tags": [ + "flatten", + "annotations", + "performance", + "pdf", + "stopwatch" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save", + "System.Diagnostics.Stopwatch" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:37:34Z", + "status": "verified" + }, + "list-annotation-names": { + "title": "List Annotation Names in PDF using PdfAnnotationEditor", + "filename": "list-annotation-names.cs", + "description": "Demonstrates how to bind a PDF with PdfAnnotationEditor, extract all annotations, and print their names to the console for debugging.", + "tags": [ + "annotations", + "pdf", + "debugging", + "facade", + "aspnet" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ExtractAnnotations", + "Annotation.Name", + "Document.Pages.Count" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:37:49Z", + "status": "verified" + }, + "delete-annotations-unit-test": { + "title": "Unit Test for DeleteAnnotations Removes All Annotations", + "filename": "delete-annotations-unit-test.cs", + "description": "Creates a PDF with an annotation, deletes all annotations using PdfAnnotationEditor, and asserts the annotation count is zero.", + "tags": [ + "annotations", + "unit-test", + "pdf", + "aspose", + "delete" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.AnnotationCollection.Count" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:38:00Z", + "status": "verified" + }, + "delete-pdf-annotation-retry": { + "title": "Delete PDF Annotation with Retry", + "filename": "delete-pdf-annotation-retry.cs", + "description": "Demonstrates how to delete a specific annotation from a PDF using PdfAnnotationEditor with a retry mechanism that rebinds the document if the first attempt fails.", + "tags": [ + "annotation", + "retry", + "pdf", + "facade", + "delete" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotation", + "PdfAnnotationEditor.Save", + "PdfAnnotationEditor.Close" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:38:15Z", + "status": "verified" + }, + "delete-annotations-with-logging": { + "title": "Delete PDF Annotations with Logging", + "filename": "delete-annotations-with-logging.cs", + "description": "Iterates through all pages, logs each annotation's name, type, and page number, deletes the annotation, and saves the updated PDF.", + "tags": [ + "annotations", + "deletion", + "logging", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.AnnotationCollection.Delete", + "Aspose.Pdf.Annotations.Annotation.Name" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:38:34Z", + "status": "verified" + }, + "delete-annotations-from-config": { + "title": "Delete Specified Annotation Types from PDF Using Config File", + "filename": "delete-annotations-from-config.cs", + "description": "Reads a list of annotation types from a configuration file and deletes those annotations from a PDF using PdfAnnotationEditor.", + "tags": [ + "annotations", + "delete", + "config", + "pdf", + "facade" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save", + "File.ReadAllLines" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:38:48Z", + "status": "verified" + }, + "remove-all-annotations": { + "title": "Remove All Annotations from PDF", + "filename": "remove-all-annotations.cs", + "description": "Removes every annotation from a PDF file using Aspose.Pdf's PdfAnnotationEditor.", + "tags": [ + "annotations", + "pdf", + "remove", + "aspdf", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save", + "PdfAnnotationEditor.Close" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:39:08Z", + "status": "verified" + }, + "batch-delete-annotations-progress": { + "title": "Batch Delete PDF Annotations with Progress Indicator", + "filename": "batch-delete-annotations-progress.cs", + "description": "Deletes all annotations from multiple PDF files while displaying a console progress percentage.", + "tags": [ + "annotations", + "batch", + "progress", + "pdf", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:39:34Z", + "status": "verified" + }, + "batch-annotation-flattening-cancel": { + "title": "Batch Annotation Flattening with Cancellation Support", + "filename": "batch-annotation-flattening-cancel.cs", + "description": "Demonstrates how to flatten all annotations in a PDF using PdfAnnotationEditor while allowing the operation to be cancelled via a CancellationToken.", + "tags": [ + "flatten", + "annotations", + "cancellation", + "pdf", + "aspose" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Multithreading.InterruptMonitor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save", + "InterruptMonitor.Interrupt", + "InterruptMonitor.CancellationToken" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:40:08Z", + "status": "verified" + }, + "get-annotation-names-by-author": { + "title": "Get Annotation Names by Author", + "filename": "get-annotation-names-by-author.cs", + "description": "Demonstrates how to retrieve the names of all annotations in a PDF that were created by a specific author.", + "tags": [ + "annotations", + "filter", + "author", + "aspdf", + "csharp" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.AnnotationCollection" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:41:08Z", + "status": "verified" + }, + "copy-annotations-template-to-multiple": { + "title": "Copy Annotations from Template PDF to Multiple PDFs", + "filename": "copy-annotations-template-to-multiple.cs", + "description": "Exports annotations from a template PDF to an in‑memory XFDF stream and imports them into several target PDFs.", + "tags": [ + "annotations", + "xfdf", + "pdf", + "copy", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ExportAnnotationsToXfdf", + "PdfAnnotationEditor.ImportAnnotationsFromXfdf", + "PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:42:55Z", + "status": "verified" + }, + "validate-no-annotations-after-flattening": { + "title": "Validate No Annotations After Flattening PDF", + "filename": "validate-no-annotations-after-flattening.cs", + "description": "Flattens all annotations in a PDF using PdfAnnotationEditor and verifies that the document contains no annotation objects.", + "tags": [ + "flatten", + "annotations", + "validation", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save", + "Document", + "Page", + "AnnotationCollection" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:43:46Z", + "status": "verified" + }, + "batch-delete-annotations-report": { + "title": "Batch Delete Annotations and Report Count per PDF", + "filename": "batch-delete-annotations-report.cs", + "description": "Deletes all annotations from each PDF in a folder, saves cleaned PDFs, and prints the number of annotations removed per file.", + "tags": [ + "annotations", + "batch", + "pdf", + "report", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.PageCollection", + "Aspose.Pdf.AnnotationCollection" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:44:04Z", + "status": "verified" + }, + "pdf-annotation-helper": { + "title": "Reusable PDF Annotation Helper for Binding, Deleting, Flattening, and Saving", + "filename": "pdf-annotation-helper.cs", + "description": "Provides a helper class that encapsulates binding a PDF, deleting annotations (all, by name, or by type), flattening annotations, and saving the modified document.", + "tags": [ + "pdf", + "annotations", + "helper", + "flatten", + "delete" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.DeleteAnnotation", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.FlatteningAnnotations(int,int,AnnotationType[])", + "PdfAnnotationEditor.Save", + "PdfAnnotationEditor.Close", + "AnnotationType" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:44:42Z", + "status": "verified" + }, + "remove-pdf-annotations": { + "title": "Remove All Annotations from PDF Stream", + "filename": "remove-pdf-annotations.cs", + "description": "Demonstrates how to accept a PDF stream, delete all annotations using PdfAnnotationEditor, and return the cleaned PDF as a stream.", + "tags": [ + "annotations", + "pdf", + "stream", + "aspnet", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:44:57Z", + "status": "verified" + }, + "async-delete-annotations": { + "title": "Asynchronously Delete All Annotations from PDF", + "filename": "async-delete-annotations.cs", + "description": "Demonstrates how to perform non‑blocking annotation operations by wrapping PdfAnnotationEditor calls in Task.Run.", + "tags": [ + "async", + "annotations", + "pdf", + "facades", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotations", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:45:09Z", + "status": "verified" + }, + "delete-annotations-folder": { + "title": "Delete All Annotations from PDFs in a Folder", + "filename": "delete-annotations-folder.cs", + "description": "Deletes all annotations from each PDF file in a specified folder using Aspose.Pdf.Facades.PdfAnnotationEditor.", + "tags": [ + "annotations", + "pdf", + "batch", + "aspnet", + "facades" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:45:20Z", + "status": "verified" + }, + "log-annotation-modification": { + "title": "Log and Update Annotation Modification Timestamps", + "filename": "log-annotation-modification.cs", + "description": "Loads a PDF, updates each annotation's Modified property with the current time, logs the change, and saves the document.", + "tags": [ + "annotation", + "timestamp", + "logging", + "pdf", + "aspose-pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation.Modified", + "Aspose.Pdf.Annotations.Annotation.AnnotationType", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:45:31Z", + "status": "verified" + }, + "delete-annotations-with-backup": { + "title": "Delete All Annotations with Backup Copy", + "filename": "delete-annotations-with-backup.cs", + "description": "Creates a backup of the original PDF, then removes all annotations using PdfAnnotationEditor.", + "tags": [ + "annotations", + "backup", + "pdf", + "delete", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save", + "PdfAnnotationEditor.Close" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:50:12Z", + "status": "verified" + }, + "delete-annotations-by-name": { + "title": "Delete PDF Annotations by Name", + "filename": "delete-annotations-by-name.cs", + "description": "Shows how to delete a PDF annotation by its name using a string literal and a variable.", + "tags": [ + "annotation", + "delete", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.DeleteAnnotation", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:50:41Z", + "status": "verified" + }, + "benchmark-delete-annotations": { + "title": "Benchmark DeleteAnnotations vs DeleteAnnotation in Aspose.Pdf", + "filename": "benchmark-delete-annotations.cs", + "description": "Measures and compares the performance of deleting all annotations at once versus deleting a single annotation by name using Aspose.Pdf.", + "tags": [ + "benchmark", + "annotations", + "performance", + "aspdf", + "csharp" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotation", + "Aspose.Pdf.Annotations.Annotation", + "System.Diagnostics.Stopwatch" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:50:59Z", + "status": "verified" + }, + "flatten-pdf-annotations__v3": { + "title": "Flatten PDF Annotations and Log Size Reduction", + "filename": "flatten-pdf-annotations__v3.cs", + "description": "Loads a PDF, flattens all annotations, saves the result, and logs the original and reduced file sizes for audit purposes.", + "tags": [ + "flatten", + "annotations", + "size", + "audit", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.Flatten", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:51:19Z", + "status": "verified" + }, + "extract-annotation-rectangles": { + "title": "Extract Annotation Rectangles to Separate PDF Pages", + "filename": "extract-annotation-rectangles.cs", + "description": "Extracts all annotation rectangles from a PDF and creates a new PDF where each page visualizes one annotation's rectangle for inspection.", + "tags": [ + "annotations", + "extraction", + "visualization", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ExtractAnnotations", + "Document", + "Document.Pages", + "Page", + "Graph", + "Aspose.Pdf.Drawing.Rectangle", + "GraphInfo", + "Annotation.Rect", + "Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:52:10Z", + "status": "verified" + }, + "modify-annotation-flags": { + "title": "Modify PDF Annotation Flags with PdfAnnotationEditor", + "filename": "modify-annotation-flags.cs", + "description": "Demonstrates how to set custom annotation flags on existing annotations using PdfAnnotationEditor.ModifyAnnotations.", + "tags": [ + "annotation", + "flags", + "pdf", + "modify", + "facades" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ModifyAnnotations", + "PdfAnnotationEditor.Save", + "TextAnnotation", + "AnnotationFlags" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:53:11Z", + "status": "verified" + }, + "flatten-pdf-annotations-nightly": { + "title": "Flatten Annotations in PDFs on Network Share (Nightly Task)", + "filename": "flatten-pdf-annotations-nightly.cs", + "description": "Console application that creates a Windows scheduled task to run nightly and flatten all annotations in PDF files located on a network share.", + "tags": [ + "pdf", + "annotations", + "flatten", + "scheduled-task", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.FlatteningAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "System.IO.Directory", + "System.IO.Path", + "System.Diagnostics.Process" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:53:32Z", + "status": "verified" + }, + "flatten-annotations-verify": { + "title": "Flatten Annotations and Verify Removal", + "filename": "flatten-annotations-verify.cs", + "description": "Flattens all annotations in a PDF and scans each page to ensure no annotation objects remain.", + "tags": [ + "flatten", + "annotations", + "validation", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.Flatten", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.AnnotationCollection", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:53:43Z", + "status": "verified" + }, + "export-annotations-pretty-xfdf": { + "title": "Export PDF Annotations to Pretty‑Printed XFDF", + "filename": "export-annotations-pretty-xfdf.cs", + "description": "Exports all annotations from a PDF to an XFDF file and formats the XML with indentation for easy manual editing.", + "tags": [ + "annotations", + "xfdf", + "export", + "xml", + "pretty-print" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ExportAnnotationsToXfdf" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:53:53Z", + "status": "verified" + }, + "pdfannotation-editor-wrapper": { + "title": "PdfAnnotationEditor Wrapper for Simplified Annotation Operations", + "filename": "pdfannotation-editor-wrapper.cs", + "description": "Demonstrates a wrapper class around Aspose.Pdf.Facades.PdfAnnotationEditor that provides easy methods to delete, flatten, export, and save PDF annotations.", + "tags": [ + "pdf", + "annotation", + "wrapper", + "aspose", + "facades" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Document", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.DeleteAnnotation", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.ExportAnnotationsToXfdf", + "PdfAnnotationEditor.Save", + "PdfAnnotationEditor.Close" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:54:15Z", + "status": "verified" + }, + "pdf-utility-cli": { + "title": "PDF Command-Line Utility for Delete, Flatten, Export", + "filename": "pdf-utility-cli.cs", + "description": "A simple CLI that can delete a page, flatten form fields, or export annotations to XFDF using Aspose.Pdf.", + "tags": [ + "pdf", + "cli", + "flatten", + "delete", + "export" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.Flatten", + "Aspose.Pdf.Document.ExportAnnotationsToXfdf", + "Aspose.Pdf.PageCollection.Delete", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:54:36Z", + "status": "verified" + }, + "export-annotations-empty-pdf": { + "title": "Export Annotations to XFDF from Empty PDF", + "filename": "export-annotations-empty-pdf.cs", + "description": "Demonstrates exporting annotations to XFDF when the PDF has no annotations and verifies the generated XFDF contains a valid root element.", + "tags": [ + "xfdf", + "export", + "annotations", + "unit-test", + "aspose-pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ExportAnnotationsToXfdf", + "Aspose.Pdf.Page" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:55:43Z", + "status": "verified" + }, + "merge-xfdf-files": { + "title": "Merge Multiple XFDF Files and Import into PDF", + "filename": "merge-xfdf-files.cs", + "description": "Demonstrates merging several XFDF files into a single XFDF document and importing the combined field data into a PDF.", + "tags": [ + "xfdf", + "merge", + "pdf", + "form", + "import" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Annotations.XfdfReader.ReadFields" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:58:24Z", + "status": "verified" + }, + "diagnostic-annotation-workflow": { + "title": "Diagnostic Annotation Workflow with Verbose Logging", + "filename": "diagnostic-annotation-workflow.cs", + "description": "Demonstrates adding annotations to a PDF while logging each step of the workflow to a verbose text file.", + "tags": [ + "annotation", + "logging", + "diagnostic", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Annotations.LinkAnnotation", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Annotations.GoToURIAction", + "Aspose.Pdf.Color", + "Aspose.Pdf.Rectangle" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:58:39Z", + "status": "verified" + }, + "annotation-count-per-page": { + "title": "Get Annotation Count Per PDF Page", + "filename": "annotation-count-per-page.cs", + "description": "Loads a PDF document and reports the total number of annotations present on each page.", + "tags": [ + "annotations", + "pdf", + "reporting", + "aspnet", + "csharp" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.AnnotationCollection.Count" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T18:58:59Z", + "status": "verified" + }, + "clone-modify-annotation": { + "title": "Clone and Modify PDF Annotation", + "filename": "clone-modify-annotation.cs", + "description": "Demonstrates cloning an existing annotation, changing its properties, and adding the clone back to the same page.", + "tags": [ + "annotation", + "clone", + "modify", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.Annotation.Clone", + "Aspose.Pdf.Annotations.AnnotationCollection.Add", + "Aspose.Pdf.Color" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:59:29Z", + "status": "verified" + }, + "batch-import-xfdf-annotations": { + "title": "Batch Import XFDF Annotations into Matching PDFs", + "filename": "batch-import-xfdf-annotations.cs", + "description": "Imports annotations from XFDF files into PDFs where the XFDF file name matches the PDF name, saving the annotated PDFs with a new filename.", + "tags": [ + "xfdf", + "annotations", + "batch", + "import", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T18:59:50Z", + "status": "verified" + }, + "concurrent-import-delete": { + "title": "Concurrent Import and Delete Operations on PDF", + "filename": "concurrent-import-delete.cs", + "description": "Demonstrates running page deletion and page import (merge) on the same PDF concurrently using tasks to test thread safety.", + "tags": [ + "concurrency", + "pdf", + "import", + "delete", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfFileEditor.TryDelete", + "Aspose.Pdf.Document.Pages.Add", + "Aspose.Pdf.Document.Save", + "System.Threading.Tasks.Task" + ], + "difficulty": "advanced", + "generated_at": "2026-03-26T19:00:12Z", + "status": "verified" + }, + "backup-before-flattening": { + "title": "Backup PDF before Flattening to Prevent Data Loss", + "filename": "backup-before-flattening.cs", + "description": "Shows how to automatically back up a PDF file before flattening its form fields and annotations, ensuring the original document remains intact.", + "tags": [ + "backup", + "flatten", + "forms", + "pdf", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Forms.FlattenSettings", + "Aspose.Pdf.Document.Flatten" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:00:45Z", + "status": "verified" + }, + "count-pdf-annotation-types": { + "title": "Count PDF Annotation Types", + "filename": "count-pdf-annotation-types.cs", + "description": "Loads a PDF, extracts all annotations, and returns a dictionary with the occurrence count for each annotation type.", + "tags": [ + "annotations", + "count", + "pdf", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExtractAnnotations", + "Aspose.Pdf.Annotations.Annotation.AnnotationType" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:01:15Z", + "status": "verified" + }, + "skip-flatten-readonly-annotations": { + "title": "Skip Flattening Read‑Only Annotations During Batch Processing", + "filename": "skip-flatten-readonly-annotations.cs", + "description": "Demonstrates how to flatten all annotations in a PDF except those marked as read‑only by iterating pages and applying Annotation.Flatten() conditionally.", + "tags": [ + "flatten", + "annotations", + "readonly", + "batch", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.AnnotationFlags" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:01:32Z", + "status": "verified" + }, + "annotation-performance-logger": { + "title": "Log Annotation Operation Durations in PDF", + "filename": "annotation-performance-logger.cs", + "description": "Demonstrates how to measure and log the time taken for adding and deleting annotations on each page of a PDF.", + "tags": [ + "annotation", + "performance", + "logging", + "stopwatch", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.AnnotationCollection.Add", + "Aspose.Pdf.AnnotationCollection.Delete", + "System.Diagnostics.Stopwatch" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:01:47Z", + "status": "verified" + }, + "delete-annotations-export-xfdf": { + "title": "Delete Specific Annotations and Export Remaining to XFDF", + "filename": "delete-annotations-export-xfdf.cs", + "description": "Demonstrates how to delete annotations of a given type from a PDF using PdfAnnotationEditor and then export the remaining annotations to an XFDF file.", + "tags": [ + "annotations", + "xfdf", + "delete", + "pdf", + "facade" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.DeleteAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExportAnnotationsToXfdf" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:02:22Z", + "status": "verified" + }, + "retry-annotation-modification": { + "title": "Retry Annotation Modification with Exponential Backoff", + "filename": "retry-annotation-modification.cs", + "description": "Demonstrates how to modify PDF annotations using PdfAnnotationEditor with a retry policy that applies exponential backoff for transient file access errors.", + "tags": [ + "annotation", + "retry", + "exponential-backoff", + "pdf", + "facades" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ModifyAnnotations", + "Aspose.Pdf.Annotation", + "Aspose.Pdf.Color" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:02:57Z", + "status": "verified" + }, + "list-annotations-csv": { + "title": "List Annotation Names and Page Numbers to CSV", + "filename": "list-annotations-csv.cs", + "description": "Extracts all annotation names from a PDF along with their page numbers and writes them to a CSV file.", + "tags": [ + "annotations", + "csv", + "aspdf", + "extract", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "System.IO.StreamWriter" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:03:10Z", + "status": "verified" + }, + "remove-old-annotations": { + "title": "Remove Old Annotations from PDF", + "filename": "remove-old-annotations.cs", + "description": "Demonstrates how to delete annotations older than a specified number of days from a PDF using Aspose.Pdf.", + "tags": [ + "annotations", + "cleanup", + "pdf", + "date", + "batch" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page.Annotations", + "Aspose.Pdf.Annotations.AnnotationCollection.Delete", + "Aspose.Pdf.Annotations.Annotation.ModifiedDate" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:06:15Z", + "status": "verified" + }, + "check-duplicate-annotation-names": { + "title": "Check for Duplicate Annotation Names in PDF", + "filename": "check-duplicate-annotation-names.cs", + "description": "Opens a PDF, scans all annotations, and reports any annotation names that appear more than once.", + "tags": [ + "annotations", + "duplicate", + "pdf", + "validation" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.AnnotationCollection", + "Aspose.Pdf.Annotations.Annotation" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:06:34Z", + "status": "verified" + }, + "extract-annotation-summary": { + "title": "Extract PDF Annotation Comments to Summary Document", + "filename": "extract-annotation-summary.cs", + "description": "Extracts all annotation comments from a PDF and compiles them into a new summary PDF.", + "tags": [ + "annotations", + "summary", + "pdf", + "extraction" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Text.TextFragment", + "Aspose.Pdf.Text.FontRepository", + "Aspose.Pdf.Document.Save", + "Aspose.Pdf.Page.Annotations", + "Aspose.Pdf.Annotations.Annotation.Contents" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:06:56Z", + "status": "verified" + }, + "preserve-annotation-appearance": { + "title": "Preserve Annotation Appearance While Removing Interactivity", + "filename": "preserve-annotation-appearance.cs", + "description": "Shows how to flatten PDF annotations into static graphics to keep their visual appearance before deleting their interactive properties.", + "tags": [ + "annotation", + "flatten", + "pdf", + "preserve", + "delete" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.Annotation.Flatten", + "Aspose.Pdf.Annotations.AnnotationCollection.Delete" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:07:18Z", + "status": "verified" + }, + "merge-annotations": { + "title": "Merge Annotations from Multiple PDFs", + "filename": "merge-annotations.cs", + "description": "Demonstrates how to combine annotation layers from several PDF files into a single PDF using PdfAnnotationEditor.", + "tags": [ + "annotations", + "merge", + "pdf", + "facades", + "c#" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ImportAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:07:37Z", + "status": "verified" + }, + "pdfannotationeditor-health-check": { + "title": "Health Check for PdfAnnotationEditor Binding", + "filename": "pdfannotationeditor-health-check.cs", + "description": "Creates a simple PDF, saves it, and verifies that PdfAnnotationEditor can bind to the file without throwing any errors.", + "tags": [ + "pdfannotationeditor", + "health-check", + "binding", + "aspdf", + "facades" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Document.Save", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.Close" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:07:58Z", + "status": "verified" + }, + "export-delete-archive-annotations": { + "title": "Export Annotations to XFDF, Delete Them, and Archive", + "filename": "export-delete-archive-annotations.cs", + "description": "Exports all annotations from each PDF to an XFDF file, removes the annotations from the PDF, saves the cleaned PDF, and archives all XFDF files into a zip archive.", + "tags": [ + "annotations", + "xfdf", + "archive", + "pdf", + "batch" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.ExportAnnotationsToXfdf", + "PdfAnnotationEditor.DeleteAnnotations", + "PdfAnnotationEditor.Save", + "System.IO.Directory", + "System.IO.File", + "System.IO.Compression.ZipArchive" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:08:30Z", + "status": "verified" + }, + "flatten-pdf-custom-output": { + "title": "Flatten PDF and Save to Custom Output Directory", + "filename": "flatten-pdf-custom-output.cs", + "description": "Flattens a PDF (removes form fields) and saves the result into a specified output directory while complying with Aspose.Pdf usage rules.", + "tags": [ + "flatten", + "pdf", + "output-directory", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.Flatten", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:08:45Z", + "status": "verified" + }, + "flatten-annotations-log-sizes": { + "title": "Flatten Annotations and Log File Sizes", + "filename": "flatten-annotations-log-sizes.cs", + "description": "Flattens all annotations in a PDF and logs the original and resulting file sizes for audit purposes.", + "tags": [ + "flatten", + "annotations", + "audit", + "filesize", + "pdf" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.FlatteningAnnotations", + "PdfAnnotationEditor.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:08:59Z", + "status": "verified" + }, + "modifyannotations-subject-test": { + "title": "Unit Test for ModifyAnnotations Subject Update", + "filename": "modifyannotations-subject-test.cs", + "description": "Demonstrates a unit test that creates a PDF with a text annotation, uses PdfAnnotationEditor.ModifyAnnotations to change its Subject, and verifies the update.", + "tags": [ + "pdf", + "annotation", + "unit-test", + "modify", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Page", + "Aspose.Pdf.Rectangle", + "NUnit.Framework.Assert" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:10:42Z", + "status": "verified" + }, + "batch-delete-annotations-retain": { + "title": "Batch Delete Annotations While Retaining Specified Types", + "filename": "batch-delete-annotations-retain.cs", + "description": "Demonstrates how to read a JSON configuration that lists annotation types to keep, then delete all other annotations from a PDF using PdfAnnotationEditor.", + "tags": [ + "annotations", + "json", + "batch", + "pdf", + "aspnet" + ], + "apis_used": [ + "PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.Save", + "Document", + "Page", + "AnnotationCollection", + "AnnotationCollection.Delete" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:11:07Z", + "status": "verified" + }, + "flatten-pdf-annotations__v4": { + "title": "Flatten PDF Annotations from Stream", + "filename": "flatten-pdf-annotations__v4.cs", + "description": "Flattens all annotations in a PDF provided as a stream and returns the modified PDF as a new stream.", + "tags": [ + "pdf", + "annotations", + "flatten", + "stream", + "aspose" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.FlatteningAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:11:31Z", + "status": "verified" + }, + "flatten-pdf-add-metadata": { + "title": "Flatten PDF and Add Flatten Date Metadata", + "filename": "flatten-pdf-add-metadata.cs", + "description": "Flattens all form fields and annotations in a PDF and records the flattening date as custom metadata.", + "tags": [ + "flatten", + "metadata", + "pdf", + "aspose", + "csharp" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.Flatten()", + "Aspose.Pdf.Document.SetCatalogValue()", + "Aspose.Pdf.Document.Save()" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:12:48Z", + "status": "verified" + }, + "export-annotations-xfdf-log": { + "title": "Export PDF Annotations to XFDF Log After Export", + "filename": "export-annotations-xfdf-log.cs", + "description": "Loads a PDF, saves it, and then writes all annotation data to an XFDF log file for diagnostic purposes.", + "tags": [ + "xfdf", + "annotations", + "diagnostic", + "export", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.Save", + "Aspose.Pdf.Document.ExportAnnotationsToXfdf" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:13:03Z", + "status": "verified" + }, + "clone-annotation-change-color": { + "title": "Clone Annotation, Change Color, and Add to Another Page", + "filename": "clone-annotation-change-color.cs", + "description": "Loads a PDF, clones an existing annotation, changes its color, and adds the cloned annotation to a different page.", + "tags": [ + "annotation", + "clone", + "color", + "pdf", + "aspnet" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Annotations.Annotation.Clone", + "Aspose.Pdf.Annotations.Annotation.Color", + "Aspose.Pdf.Page.Annotations.Add" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:13:39Z", + "status": "verified" + }, + "batch-process-azure-pdf": { + "title": "Batch Process PDFs from Azure Blob Storage using PdfAnnotationEditor", + "filename": "batch-process-azure-pdf.cs", + "description": "Streams each PDF blob from Azure Blob Storage into Aspose.Pdf.Facades.PdfAnnotationEditor, processes it, and uploads the result back.", + "tags": [ + "azure", + "blob", + "batch", + "pdf", + "annotation" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "PdfAnnotationEditor.BindPdf", + "PdfAnnotationEditor.Save", + "Azure.Storage.Blobs.BlobServiceClient", + "BlobContainerClient.GetBlobs" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:14:28Z", + "status": "verified" + }, + "annotation-summary-report": { + "title": "Generate Annotation Type Summary Report for PDFs", + "filename": "annotation-summary-report.cs", + "description": "Scans one or more PDF files, counts each annotation type present, and prints a summary to the console.", + "tags": [ + "annotations", + "summary", + "pdf", + "report", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Annotations.AnnotationType" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:14:44Z", + "status": "verified" + }, + "safeguard-flattening-signatures": { + "title": "Safeguard Flattening When PDF Has Digital Signatures", + "filename": "safeguard-flattening-signatures.cs", + "description": "Loads a PDF, checks for digital signatures, and only flattens the document if no signatures are present, preserving signature validity.", + "tags": [ + "flatten", + "digital-signature", + "pdf", + "aspdf", + "safety" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Facades.PdfFileSignature.ContainsSignature", + "Aspose.Pdf.Document.Flatten", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:14:54Z", + "status": "verified" + }, + "rename-annotation-names": { + "title": "Rename PDF Annotation Names with Standard Prefix", + "filename": "rename-annotation-names.cs", + "description": "Loads a PDF, prefixes each annotation's name with a standard string, and saves the modified document.", + "tags": [ + "annotations", + "rename", + "batch", + "pdf", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Annotations.Annotation", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:15:06Z", + "status": "verified" + }, + "add-annotation-verbose-logging": { + "title": "Add Annotation with Verbose Logging", + "filename": "add-annotation-verbose-logging.cs", + "description": "Demonstrates how to enable verbose logging for annotation operations via a command‑line flag and add a text annotation to a PDF.", + "tags": [ + "annotation", + "logging", + "command-line", + "aspdf", + "csharp" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Page", + "Aspose.Pdf.Rectangle", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Document.EnableNotificationLogging" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:15:20Z", + "status": "verified" + }, + "export-annotations-unbound-test": { + "title": "ExportAnnotations throws exception on unbound PdfAnnotationEditor", + "filename": "export-annotations-unbound-test.cs", + "description": "Demonstrates that calling ExportAnnotationsToXfdf on a PdfAnnotationEditor that hasn't been bound to a PDF throws an exception.", + "tags": [ + "pdf", + "annotations", + "exception", + "facade" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExportAnnotationsToXfdf" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:15:30Z", + "status": "verified" + }, + "extract-annotation-authors": { + "title": "Extract and Group PDF Annotations by Author", + "filename": "extract-annotation-authors.cs", + "description": "Loads a PDF, extracts all annotations, groups them by their author and prints a summary report.", + "tags": [ + "annotations", + "author", + "grouping", + "pdf", + "report" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.ExtractAnnotations", + "Aspose.Pdf.Document", + "Aspose.Pdf.Annotations.Annotation.Author", + "Aspose.Pdf.Annotations.AnnotationType" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:16:02Z", + "status": "verified" + }, + "export-annotations-xfdf-custom-namespace": { + "title": "Export PDF Annotations to XFDF with Custom Namespace", + "filename": "export-annotations-xfdf-custom-namespace.cs", + "description": "Exports annotations from a PDF to an XFDF file and replaces the default namespace with a custom one to meet enterprise XML standards.", + "tags": [ + "xfdf", + "annotations", + "export", + "custom-namespace", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Annotations.TextAnnotation", + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "System.Xml.Linq.XDocument" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:16:47Z", + "status": "verified" + }, + "folder-monitor-flatten-pdf-annotations": { + "title": "Folder Monitor to Flatten PDF Annotations", + "filename": "folder-monitor-flatten-pdf-annotations.cs", + "description": "Monitors a folder for new PDF files and automatically flattens all their annotations.", + "tags": [ + "pdf", + "annotation", + "folder-watcher", + "flatten", + "automation" + ], + "apis_used": [ + "Aspose.Pdf.Facades.PdfAnnotationEditor", + "Aspose.Pdf.Facades.PdfAnnotationEditor.BindPdf", + "Aspose.Pdf.Facades.PdfAnnotationEditor.FlatteningAnnotations", + "Aspose.Pdf.Facades.PdfAnnotationEditor.Save", + "System.IO.FileSystemWatcher" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:19:28Z", + "status": "verified" + }, + "validate-pdf-integrity": { + "title": "Validate PDF Integrity After Annotation Modification", + "filename": "validate-pdf-integrity.cs", + "description": "Loads a PDF, adds a text annotation, validates the document for corrupted objects, and saves the modified file.", + "tags": [ + "validation", + "annotations", + "integrity", + "pdf", + "aspnet" + ], + "apis_used": [ + "Document", + "TextAnnotation", + "Document.Validate", + "PdfFormat" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:20:00Z", + "status": "verified" + }, + "export-annotations-xfdf-gzip": { + "title": "Export PDF Annotations to XFDF and Compress with GZip", + "filename": "export-annotations-xfdf-gzip.cs", + "description": "Exports all annotations from a PDF to an XFDF file and compresses the result using GZip for efficient storage.", + "tags": [ + "annotations", + "xfdf", + "gzip", + "export", + "aspdf" + ], + "apis_used": [ + "Aspose.Pdf.Document" + ], + "difficulty": "intermediate", + "generated_at": "2026-03-26T19:20:21Z", + "status": "verified" + }, + "import-xfdf-and-cleanup": { + "title": "Import XFDF Annotations and Delete Temporary File", + "filename": "import-xfdf-and-cleanup.cs", + "description": "Demonstrates importing annotations from an XFDF file into a PDF and deleting the temporary XFDF file after a successful import.", + "tags": [ + "xfdf", + "import", + "cleanup", + "annotations", + "pdf" + ], + "apis_used": [ + "Aspose.Pdf.Document", + "Aspose.Pdf.Document.ImportAnnotationsFromXfdf", + "Aspose.Pdf.Document.Save" + ], + "difficulty": "beginner", + "generated_at": "2026-03-26T19:20:39Z", + "status": "verified" + } + } +} \ No newline at end of file diff --git a/facades-annotations/list-annotation-names.cs b/facades-annotations/list-annotation-names.cs new file mode 100644 index 00000000..5c0bfa25 --- /dev/null +++ b/facades-annotations/list-annotation-names.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + + // Get total number of pages from the bound document + Document boundDoc = editor.Document; + int pageCount = boundDoc.Pages.Count; + + // Extract all annotations (passing null for types returns all) + IList annotationList = editor.ExtractAnnotations(1, pageCount, (string[])null); + + Console.WriteLine($"Total annotations found: {annotationList.Count}"); + foreach (Annotation annotation in annotationList) + { + // Annotation.Name holds the unique name identifier + Console.WriteLine($"Annotation Name: {annotation.Name}"); + } + + // Clean up the facade + editor.Close(); + } +} \ No newline at end of file diff --git a/facades-annotations/list-annotations-csv.cs b/facades-annotations/list-annotations-csv.cs new file mode 100644 index 00000000..d51acd71 --- /dev/null +++ b/facades-annotations/list-annotations-csv.cs @@ -0,0 +1,41 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputCsv = "annotations.csv"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input PDF not found: " + inputPath); + return; + } + + using (Document doc = new Document(inputPath)) + { + using (StreamWriter writer = new StreamWriter(outputCsv)) + { + writer.WriteLine("AnnotationName,PageNumber"); + int pageCount = doc.Pages.Count; + for (int pageIndex = 1; pageIndex <= pageCount; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + AnnotationCollection annCollection = page.Annotations; + for (int annIndex = 1; annIndex <= annCollection.Count; annIndex++) + { + Annotation annotation = annCollection[annIndex]; + string name = annotation.Name ?? string.Empty; + writer.WriteLine(name + "," + pageIndex); + } + } + } + } + + Console.WriteLine("Annotations exported to " + outputCsv); + } +} diff --git a/facades-annotations/log-annotation-modification.cs b/facades-annotations/log-annotation-modification.cs new file mode 100644 index 00000000..6379f45d --- /dev/null +++ b/facades-annotations/log-annotation-modification.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + // Iterate through all pages and their annotations + foreach (Page page in doc.Pages) + { + foreach (Annotation annotation in page.Annotations) + { + DateTime now = DateTime.Now; + annotation.Modified = now; + Console.WriteLine($"Page {page.Number}, Annotation Type {annotation.AnnotationType}, Modified set to {now}"); + } + } + + // Save the updated PDF + doc.Save(outputPath); + } + + Console.WriteLine($"Modified PDF saved as '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/measure-flatten-annotations.cs b/facades-annotations/measure-flatten-annotations.cs new file mode 100644 index 00000000..48f8be51 --- /dev/null +++ b/facades-annotations/measure-flatten-annotations.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; +using System.Diagnostics; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened_output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + + // Flatten all annotations in the document + editor.FlatteningAnnotations(); + + stopwatch.Stop(); + + editor.Save(outputPath); + + Console.WriteLine($"Flattening completed in {stopwatch.Elapsed.TotalSeconds} seconds."); + } +} diff --git a/facades-annotations/merge-annotations.cs b/facades-annotations/merge-annotations.cs new file mode 100644 index 00000000..667bc527 --- /dev/null +++ b/facades-annotations/merge-annotations.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +public class AnnotationMerger +{ + public static void MergeAnnotations(string basePdfPath, string[] annotationPdfPaths, string outputPdfPath) + { + if (!File.Exists(basePdfPath)) + { + Console.Error.WriteLine($"Base PDF not found: {basePdfPath}"); + return; + } + + foreach (string path in annotationPdfPaths) + { + if (!File.Exists(path)) + { + Console.Error.WriteLine($"Annotation source PDF not found: {path}"); + return; + } + } + + // Bind the base PDF to the editor and import annotations from the other PDFs + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(basePdfPath); + editor.ImportAnnotations(annotationPdfPaths); + editor.Save(outputPdfPath); + } + + Console.WriteLine($"Annotations merged into '{outputPdfPath}'."); + } + + // Example usage + public static void Main() + { + string basePdf = "base.pdf"; + string[] sources = new string[] { "doc1.pdf", "doc2.pdf", "doc3.pdf" }; + string resultPdf = "merged_annotations.pdf"; + + MergeAnnotations(basePdf, sources, resultPdf); + } +} \ No newline at end of file diff --git a/facades-annotations/merge-xfdf-files.cs b/facades-annotations/merge-xfdf-files.cs new file mode 100644 index 00000000..479ce83e --- /dev/null +++ b/facades-annotations/merge-xfdf-files.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + // Paths to the source PDF and the output PDF + string inputPdfPath = "input.pdf"; + string outputPdfPath = "merged_output.pdf"; + + // List of XFDF files that need to be merged + string[] xfdfFiles = new string[] { "data1.xfdf", "data2.xfdf", "data3.xfdf" }; + + // Validate that the source PDF exists + if (!File.Exists(inputPdfPath)) + { + Console.Error.WriteLine($"Input PDF not found: {inputPdfPath}"); + return; + } + + // Validate that each XFDF file exists + foreach (string xfdfPath in xfdfFiles) + { + if (!File.Exists(xfdfPath)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfPath}"); + return; + } + } + + try + { + // Create a Form object that will read the source PDF and write to the output PDF + Form form = new Form(inputPdfPath, outputPdfPath); + + // Import each XFDF file sequentially – this merges their field data into the PDF + foreach (string xfdfPath in xfdfFiles) + { + FileStream xfdfStream = new FileStream(xfdfPath, FileMode.Open, FileAccess.Read); + form.ImportXfdf(xfdfStream); + xfdfStream.Close(); + } + + // Save the resulting PDF with all merged XFDF data + form.Save(); + Console.WriteLine($"Merged XFDF data saved to '{outputPdfPath}'."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/modify-annotation-author.cs b/facades-annotations/modify-annotation-author.cs new file mode 100644 index 00000000..eaa7c557 --- /dev/null +++ b/facades-annotations/modify-annotation-author.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + const string oldAuthor = "Old Author"; + const string newAuthor = "New Author"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + // Modify author of annotations on page 3 (start = 3, end = 3) + editor.ModifyAnnotationsAuthor(3, 3, oldAuthor, newAuthor); + editor.Save(outputPath); + editor.Close(); + + Console.WriteLine($"Author modified and saved to '{outputPath}'."); + } +} diff --git a/facades-annotations/modify-annotation-flags.cs b/facades-annotations/modify-annotation-flags.cs new file mode 100644 index 00000000..bcddcb08 --- /dev/null +++ b/facades-annotations/modify-annotation-flags.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + // ------------------------------------------------------------ + // Ensure the source PDF exists – create a minimal document if + // it does not. This prevents the FileNotFoundException that + // occurred in the original sample. + // ------------------------------------------------------------ + if (!File.Exists(inputPath)) + { + using (var tempDoc = new Document()) + { + // Add a single blank page so that the annotation editor + // has a page to bind to. + tempDoc.Pages.Add(); + tempDoc.Save(inputPath); + } + } + + // Load the PDF into the annotation editor + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + + // Load the document to obtain a Page object (required for TextAnnotation ctor) + using (Document doc = new Document(inputPath)) + { + // Choose the page where the annotation will be placed + Page page = doc.Pages[1]; + + // Define the rectangle (position and size) of the annotation + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 500, 200, 600); + + // ------------------------------------------------------------ + // Create a TextAnnotation with custom (user‑defined) flags. + // Aspose.Pdf does not expose a dedicated property for custom + // flags, but the underlying PDF specification allows any bit + // in the Flags field. We can therefore cast an integer value + // to AnnotationFlags and combine it with the standard flags. + // ------------------------------------------------------------ + const int CustomFlagValue = 0x8000; // Example custom flag (bit 15) + AnnotationFlags customFlags = (AnnotationFlags)CustomFlagValue; + + TextAnnotation annotation = new TextAnnotation(page, rect) + { + // Combine built‑in flags with the custom flag using bitwise OR + Flags = AnnotationFlags.Hidden | AnnotationFlags.NoView | customFlags, + Title = "Custom Flags", + Contents = "This annotation has hidden, no‑view, and a custom flag.", + Color = Aspose.Pdf.Color.Red, + Open = true + }; + + // Apply the modified annotation to pages 1 through 1 + editor.ModifyAnnotations(1, 1, annotation); + } + + // Save the updated PDF + editor.Save(outputPath); + } +} diff --git a/facades-annotations/modify-annotation-subject-color.cs b/facades-annotations/modify-annotation-subject-color.cs new file mode 100644 index 00000000..edf7630f --- /dev/null +++ b/facades-annotations/modify-annotation-subject-color.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + // Load the document to obtain a Page object required by TextAnnotation constructor + Document doc = new Document(inputPath); + Page page = doc.Pages[1]; + // Define a rectangle for the annotation (position and size). Adjust coordinates as needed. + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 100, 200, 200); + + // Create the TextAnnotation using the (Page, Rectangle) constructor + TextAnnotation annotation = new TextAnnotation(page, rect) + { + Subject = "Updated Subject", + Color = Aspose.Pdf.Color.Blue + }; + + // Use PdfAnnotationEditor to modify annotations on page 1 (start = 1, end = 1) + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + editor.ModifyAnnotations(1, 1, annotation); + editor.Save(outputPath); + editor.Close(); + + Console.WriteLine($"Annotations updated and saved to '{outputPath}'."); + } +} diff --git a/facades-annotations/modifyannotations-subject-test.cs b/facades-annotations/modifyannotations-subject-test.cs new file mode 100644 index 00000000..faa3c7e0 --- /dev/null +++ b/facades-annotations/modifyannotations-subject-test.cs @@ -0,0 +1,97 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; +using NUnit.Framework; // <-- added using directive for the stub namespace + +// Minimal NUnit stub to allow compilation without the real NUnit package +namespace NUnit.Framework +{ + [AttributeUsage(AttributeTargets.Class)] + public sealed class TestFixtureAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Method)] + public sealed class TestAttribute : Attribute { } + + public static class Assert + { + public static void AreEqual(T expected, T actual, string message = null) + { + if (!object.Equals(expected, actual)) + throw new Exception(message ?? $"Assert.AreEqual failed. Expected:<{expected}>. Actual:<{actual}>."); + } + + public static void IsInstanceOf(object obj, string message = null) + { + if (!(obj is T)) + throw new Exception(message ?? $"Assert.IsInstanceOf failed. Object is not of type {typeof(T).FullName}."); + } + } +} + +[TestFixture] +public class PdfAnnotationEditorTests +{ + private const string OriginalFile = "original.pdf"; + private const string ModifiedFile = "modified.pdf"; + + [Test] + public void ModifyAnnotations_UpdatesSubjectProperty() + { + // Clean up any previous files + if (File.Exists(OriginalFile)) + File.Delete(OriginalFile); + if (File.Exists(ModifiedFile)) + File.Delete(ModifiedFile); + + // Create a PDF with a single text annotation whose Subject is "Old Subject" + using (Document doc = new Document()) + { + Page page = doc.Pages.Add(); + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 500, 300, 550); + TextAnnotation annotation = new TextAnnotation(page, rect); + annotation.Subject = "Old Subject"; + annotation.Contents = "Sample annotation"; + page.Annotations.Add(annotation); + doc.Save(OriginalFile); + } + + // Use PdfAnnotationEditor to modify the Subject property + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(OriginalFile); + + // Create a temporary TextAnnotation instance (required constructor) to hold new values + Document tempDoc = new Document(); + Page tempPage = tempDoc.Pages.Add(); + Aspose.Pdf.Rectangle tempRect = new Aspose.Pdf.Rectangle(0, 0, 0, 0); + TextAnnotation newValues = new TextAnnotation(tempPage, tempRect) + { + Subject = "New Subject" + }; + + // Modify annotations on page 1 (start = 1, end = 1) + editor.ModifyAnnotations(1, 1, newValues); + editor.Save(ModifiedFile); + editor.Close(); + + // Verify that the Subject was updated to "New Subject" + using (Document modifiedDoc = new Document(ModifiedFile)) + { + Page modifiedPage = modifiedDoc.Pages[1]; + Annotation retrieved = modifiedPage.Annotations[1]; + Assert.IsInstanceOf(retrieved); + TextAnnotation retrievedText = (TextAnnotation)retrieved; + Assert.AreEqual("New Subject", retrievedText.Subject); + } + } +} + +// Dummy entry point to satisfy the compiler for a console‑type project +public static class Program +{ + public static void Main() + { + // No runtime logic required – tests are executed by the test runner. + } +} \ No newline at end of file diff --git a/facades-annotations/pdf-annotation-helper.cs b/facades-annotations/pdf-annotation-helper.cs new file mode 100644 index 00000000..9146b3ee --- /dev/null +++ b/facades-annotations/pdf-annotation-helper.cs @@ -0,0 +1,125 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +public class PdfAnnotationHelper : IDisposable +{ + private readonly PdfAnnotationEditor _editor; + private bool _isBound = false; + + public PdfAnnotationHelper() + { + _editor = new PdfAnnotationEditor(); + } + + /// + /// Binds the helper to an existing PDF file. If the file does not exist, a simple one‑page PDF is created automatically. + /// + /// Path to the PDF file. + public void Bind(string pdfPath) + { + if (string.IsNullOrWhiteSpace(pdfPath)) + throw new ArgumentException("PDF path cannot be null or empty.", nameof(pdfPath)); + + // If the file is missing, create a minimal PDF so the rest of the workflow can continue. + if (!File.Exists(pdfPath)) + { + var doc = new Document(); + doc.Pages.Add(); + doc.Save(pdfPath); + } + + _editor.BindPdf(pdfPath); + _isBound = true; + } + + public void DeleteAll() + { + EnsureBound(); + _editor.DeleteAnnotations(); + } + + public void DeleteByName(string annotationName) + { + EnsureBound(); + if (string.IsNullOrEmpty(annotationName)) + throw new ArgumentException("Annotation name cannot be null or empty.", nameof(annotationName)); + _editor.DeleteAnnotation(annotationName); + } + + public void DeleteByTypes(AnnotationType[] types) + { + EnsureBound(); + if (types == null) throw new ArgumentNullException(nameof(types)); + foreach (AnnotationType type in types) + { + // PdfAnnotationEditor expects the annotation subtype as a string. + _editor.DeleteAnnotations(type.ToString()); + } + } + + public void FlattenAll() + { + EnsureBound(); + _editor.FlatteningAnnotations(); + } + + public void FlattenRange(int startPage, int endPage, AnnotationType[] types) + { + EnsureBound(); + if (startPage < 1 || endPage < startPage) + throw new ArgumentException("Invalid page range supplied."); + _editor.FlatteningAnnotations(startPage, endPage, types); + } + + public void Save(string outputPath) + { + EnsureBound(); + if (string.IsNullOrWhiteSpace(outputPath)) + throw new ArgumentException("Output path cannot be null or empty.", nameof(outputPath)); + _editor.Save(outputPath); + } + + public void Close() + { + if (_isBound) + { + _editor.Close(); + _isBound = false; + } + } + + private void EnsureBound() + { + if (!_isBound) + throw new InvalidOperationException("PdfAnnotationHelper is not bound to a PDF. Call Bind() first."); + } + + public void Dispose() + { + Close(); + _editor?.Dispose(); + } +} + +public class Program +{ + public static void Main() + { + string inputPdf = "sample.pdf"; + string outputPdf = "sample_clean.pdf"; + + // Use a using‑statement to guarantee proper disposal of resources. + using (var helper = new PdfAnnotationHelper()) + { + helper.Bind(inputPdf); + helper.DeleteAll(); + helper.FlattenAll(); + helper.Save(outputPdf); + } + + Console.WriteLine($"Annotations processed and saved to '{outputPdf}'."); + } +} diff --git a/facades-annotations/pdf-utility-cli.cs b/facades-annotations/pdf-utility-cli.cs new file mode 100644 index 00000000..dc93db26 --- /dev/null +++ b/facades-annotations/pdf-utility-cli.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using Aspose.Pdf; + +namespace PdfUtilityCli +{ + class Program + { + static void Main(string[] args) + { + if (args == null || args.Length < 3) + { + Console.Error.WriteLine("Usage: [pageNumber]"); + Console.Error.WriteLine("Operations: delete, flatten, export"); + return; + } + + string operation = args[0].ToLowerInvariant(); + string inputPath = args[1]; + string outputPath = args[2]; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + switch (operation) + { + case "delete": + // Delete a page. If a page number is supplied use it, otherwise delete the last page. + int pageNumber = 0; + if (args.Length > 3) + { + int.TryParse(args[3], out pageNumber); + } + if (pageNumber <= 0 || pageNumber > doc.Pages.Count) + { + pageNumber = doc.Pages.Count; // delete last page by default + } + doc.Pages.Delete(pageNumber); + doc.Save(outputPath); + Console.WriteLine($"Page {pageNumber} deleted. Saved to '{outputPath}'."); + break; + + case "flatten": + // Flatten form fields and annotations. + doc.Flatten(); + doc.Save(outputPath); + Console.WriteLine($"Document flattened. Saved to '{outputPath}'."); + break; + + case "export": + // Export all annotations to an XFDF file. + doc.ExportAnnotationsToXfdf(outputPath); + Console.WriteLine($"Annotations exported to XFDF file '{outputPath}'."); + break; + + default: + Console.Error.WriteLine($"Unsupported operation: {operation}"); + break; + } + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } + } +} diff --git a/facades-annotations/pdfannotation-editor-wrapper.cs b/facades-annotations/pdfannotation-editor-wrapper.cs new file mode 100644 index 00000000..7d32ae89 --- /dev/null +++ b/facades-annotations/pdfannotation-editor-wrapper.cs @@ -0,0 +1,116 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +namespace PdfAnnotationHelper +{ + // Abstract wrapper exposing simplified annotation operations + public abstract class PdfAnnotationEditorWrapper : IDisposable + { + protected PdfAnnotationEditor editor; + protected Document document; + + protected PdfAnnotationEditorWrapper(Document doc) + { + this.document = doc; + this.editor = new PdfAnnotationEditor(this.document); + } + + // Deletes a specific annotation by its name + public void DeleteAnnotation(string annotationName) + { + this.editor.DeleteAnnotation(annotationName); + } + + // Deletes all annotations in the document + public void DeleteAllAnnotations() + { + this.editor.DeleteAnnotations(); + } + + // Deletes all annotations of a specific type (e.g., "Text") + public void DeleteAnnotationsByType(string annotationType) + { + this.editor.DeleteAnnotations(annotationType); + } + + // Flattens all annotations (makes them part of the page content) + public void FlattenAllAnnotations() + { + this.editor.FlatteningAnnotations(); + } + + // Exports all annotations to an XFDF file + public void ExportAnnotations(string xfdfFilePath) + { + using (FileStream fs = new FileStream(xfdfFilePath, FileMode.Create, FileAccess.Write)) + { + this.editor.ExportAnnotationsToXfdf(fs); + } + } + + // Saves the modified PDF to a new file + public void Save(string outputFilePath) + { + this.editor.Save(outputFilePath); + } + + // Releases resources held by the facade and the underlying document + public void Dispose() + { + if (this.editor != null) + { + this.editor.Close(); + this.editor = null; + } + if (this.document != null) + { + this.document.Dispose(); + this.document = null; + } + } + } + + // Concrete implementation used by client code + public sealed class SimplePdfAnnotationEditor : PdfAnnotationEditorWrapper + { + public SimplePdfAnnotationEditor(string pdfPath) : base(new Document(pdfPath)) + { + } + } + + // Sample usage + public class Program + { + public static void Main() + { + const string inputPdf = "input.pdf"; + const string outputPdf = "output.pdf"; + const string xfdfPath = "annotations.xfdf"; + + if (!File.Exists(inputPdf)) + { + Console.Error.WriteLine($"File not found: {inputPdf}"); + return; + } + + using (SimplePdfAnnotationEditor editor = new SimplePdfAnnotationEditor(inputPdf)) + { + // Remove all existing annotations + editor.DeleteAllAnnotations(); + + // Flatten any remaining annotations (if any) + editor.FlattenAllAnnotations(); + + // Export the (now empty) annotation set to XFDF for demonstration + editor.ExportAnnotations(xfdfPath); + + // Save the resulting PDF + editor.Save(outputPdf); + } + + Console.WriteLine($"Processed PDF saved as '{outputPdf}'. XFDF exported to '{xfdfPath}'."); + } + } +} diff --git a/facades-annotations/pdfannotationeditor-health-check.cs b/facades-annotations/pdfannotationeditor-health-check.cs new file mode 100644 index 00000000..2e820c3e --- /dev/null +++ b/facades-annotations/pdfannotationeditor-health-check.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string samplePath = "sample.pdf"; + + // Create a simple PDF with one blank page and save it + using (Document doc = new Document()) + { + Page page = doc.Pages.Add(); + doc.Save(samplePath); + } + + // Verify that PdfAnnotationEditor can bind to the created PDF without errors + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + editor.BindPdf(samplePath); + // Close releases the bound document; Dispose will be called automatically by using + editor.Close(); + } + + Console.WriteLine("PdfAnnotationEditor bound successfully to the sample PDF."); + } +} \ No newline at end of file diff --git a/facades-annotations/preserve-annotation-appearance.cs b/facades-annotations/preserve-annotation-appearance.cs new file mode 100644 index 00000000..8b7aeead --- /dev/null +++ b/facades-annotations/preserve-annotation-appearance.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + // Set to true to keep the visual look of annotations (flatten them) before removal. + bool preserveAppearance = true; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + // Iterate backwards because we may delete items from the collection. + for (int annIndex = page.Annotations.Count; annIndex >= 1; annIndex--) + { + Annotation annotation = page.Annotations[annIndex]; + if (preserveAppearance) + { + // Convert the annotation to a static graphic on the page. + annotation.Flatten(); + } + else + { + // Directly delete the annotation without preserving its appearance. + page.Annotations.Delete(annIndex); + } + } + } + + doc.Save(outputPath); + Console.WriteLine($"Processed PDF saved as '{outputPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/remove-all-annotations.cs b/facades-annotations/remove-all-annotations.cs new file mode 100644 index 00000000..e8c33479 --- /dev/null +++ b/facades-annotations/remove-all-annotations.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main(string[] args) + { + if (args.Length < 2) + { + Console.Error.WriteLine("Usage: "); + return; + } + + string inputPath = args[0]; + string outputPath = args[1]; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + try + { + editor.BindPdf(inputPath); + editor.DeleteAnnotations(); + editor.Save(outputPath); + Console.WriteLine($"All annotations removed. Saved to '{outputPath}'."); + } + finally + { + editor.Close(); + } + } +} \ No newline at end of file diff --git a/facades-annotations/remove-link-annotations.cs b/facades-annotations/remove-link-annotations.cs new file mode 100644 index 00000000..3f4f284b --- /dev/null +++ b/facades-annotations/remove-link-annotations.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!System.IO.File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + + string[] annotationTypes = new string[] { "Link" }; + IList linkAnnotations = editor.ExtractAnnotations(3, 7, annotationTypes); + + foreach (Annotation annotation in linkAnnotations) + { + if (!string.IsNullOrEmpty(annotation.Name)) + { + editor.DeleteAnnotation(annotation.Name); + } + } + + editor.Save(outputPath); + editor.Close(); + + Console.WriteLine("Link annotations removed from pages 3-7 and saved to '" + outputPath + "'."); + } +} \ No newline at end of file diff --git a/facades-annotations/remove-old-annotations.cs b/facades-annotations/remove-old-annotations.cs new file mode 100644 index 00000000..cfe76c13 --- /dev/null +++ b/facades-annotations/remove-old-annotations.cs @@ -0,0 +1,64 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "cleaned.pdf"; + const int daysThreshold = 30; // remove annotations older than 30 days + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + DateTime cutoffDate = DateTime.Now.AddDays(-daysThreshold); + + try + { + using (Document doc = new Document(inputPath)) + { + // Iterate through all pages + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + AnnotationCollection annotations = page.Annotations; + List indicesToDelete = new List(); + + // Collect indices of annotations that are older than the cutoff date + for (int annIndex = 1; annIndex <= annotations.Count; annIndex++) + { + Annotation annotation = annotations[annIndex]; + if (annotation is MarkupAnnotation markupAnnotation) + { + // The Modified property holds the last modification date of the annotation + if (markupAnnotation.Modified < cutoffDate) + { + indicesToDelete.Add(annIndex); + } + } + } + + // Delete collected annotations starting from the highest index to avoid re‑indexing issues + for (int i = indicesToDelete.Count - 1; i >= 0; i--) + { + annotations.Delete(indicesToDelete[i]); + } + } + + doc.Save(outputPath); + Console.WriteLine($"Old annotations removed. Saved cleaned PDF to '{outputPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error processing PDF: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/remove-pdf-annotations.cs b/facades-annotations/remove-pdf-annotations.cs new file mode 100644 index 00000000..16e67c41 --- /dev/null +++ b/facades-annotations/remove-pdf-annotations.cs @@ -0,0 +1,41 @@ +using System; +using System.IO; +using Aspose.Pdf.Facades; + +namespace AsposePdfApi +{ + public class PdfService + { + public Stream RemoveAllAnnotations(Stream pdfInput) + { + if (pdfInput == null) + throw new ArgumentNullException(nameof(pdfInput)); + + var cleanedPdf = new MemoryStream(); + + using (var annotationEditor = new PdfAnnotationEditor()) + { + annotationEditor.BindPdf(pdfInput); + annotationEditor.DeleteAnnotations(); + annotationEditor.Save(cleanedPdf); + } + + cleanedPdf.Position = 0; + return cleanedPdf; + } + } + + // Minimal entry point to satisfy the compiler when the project is built as an executable. + internal class Program + { + private static void Main(string[] args) + { + // Placeholder – no operation required. + // Example usage (optional, can be removed in production): + // var service = new PdfService(); + // using var input = File.OpenRead("input.pdf"); + // using var output = service.RemoveAllAnnotations(input); + // File.WriteAllBytes("output.pdf", ((MemoryStream)output).ToArray()); + } + } +} \ No newline at end of file diff --git a/facades-annotations/rename-annotation-names.cs b/facades-annotations/rename-annotation-names.cs new file mode 100644 index 00000000..9df81e43 --- /dev/null +++ b/facades-annotations/rename-annotation-names.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "renamed_annotations.pdf"; + const string prefix = "STD_"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + foreach (Page page in doc.Pages) + { + foreach (Annotation annotation in page.Annotations) + { + string originalName = annotation.Name; + if (!string.IsNullOrEmpty(originalName)) + { + annotation.Name = prefix + originalName; + } + } + } + + doc.Save(outputPath); + } + + Console.WriteLine($"Annotations renamed and saved to '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/retry-annotation-modification.cs b/facades-annotations/retry-annotation-modification.cs new file mode 100644 index 00000000..31991e04 --- /dev/null +++ b/facades-annotations/retry-annotation-modification.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Threading; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine("Input file not found: " + inputPath); + return; + } + + const int maxRetries = 5; + const int initialDelayMs = 200; + + using (Document document = new Document(inputPath)) + { + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(document); + + // Create a concrete annotation type (TextAnnotation) – Annotation is abstract. + // A rectangle is required for the annotation; values are arbitrary for the example. + var rect = new Aspose.Pdf.Rectangle(100, 100, 200, 200); + TextAnnotation annotation = new TextAnnotation(document.Pages[1], rect) + { + Title = "Updated Title", + Contents = "Updated annotation contents.", + Color = Aspose.Pdf.Color.Yellow + }; + + int attempt = 0; + int delayMs = initialDelayMs; + while (true) + { + try + { + // Modify annotations on page 1 (page range is inclusive) + editor.ModifyAnnotations(1, 1, annotation); + break; + } + catch (IOException ioEx) + { + attempt++; + if (attempt > maxRetries) + { + Console.Error.WriteLine("Failed to modify annotations after retries: " + ioEx.Message); + throw; + } + Console.WriteLine($"Transient error encountered, retrying in {delayMs} ms..."); + Thread.Sleep(delayMs); + delayMs *= 2; // exponential back‑off + } + } + + document.Save(outputPath); + Console.WriteLine($"Annotations modified and saved to '{outputPath}'."); + } + } +} diff --git a/facades-annotations/safeguard-flattening-signatures.cs b/facades-annotations/safeguard-flattening-signatures.cs new file mode 100644 index 00000000..a13adef3 --- /dev/null +++ b/facades-annotations/safeguard-flattening-signatures.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document document = new Document(inputPath)) + { + // Initialize the signature facade with the loaded document + PdfFileSignature signatureFacade = new PdfFileSignature(document); + bool hasSignature = signatureFacade.ContainsSignature(); + + if (hasSignature) + { + Console.WriteLine("Document contains digital signatures. Skipping flattening to preserve signature validity."); + } + else + { + // No signatures present – safe to flatten the form fields + document.Flatten(); + Console.WriteLine("Document flattened successfully."); + } + + // Save the (potentially flattened) document + document.Save(outputPath); + } + + Console.WriteLine($"Processed file saved as '{outputPath}'."); + } +} \ No newline at end of file diff --git a/facades-annotations/set-annotations-open.cs b/facades-annotations/set-annotations-open.cs new file mode 100644 index 00000000..6a0735bc --- /dev/null +++ b/facades-annotations/set-annotations-open.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + try + { + using (Document doc = new Document(inputPath)) + { + // Iterate through all pages (1‑based indexing) + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + + // Iterate through all annotations on the page (1‑based indexing) + for (int annIndex = 1; annIndex <= page.Annotations.Count; annIndex++) + { + Annotation annotation = page.Annotations[annIndex]; + + // Set the Open flag where the property exists + if (annotation is TextAnnotation textAnn) + { + textAnn.Open = true; + } + else if (annotation is PopupAnnotation popupAnn) + { + popupAnn.Open = true; + } + } + } + + // Save the modified document + doc.Save(outputPath); + Console.WriteLine($"All annotation Open flags set. Saved to '{outputPath}'."); + } + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/facades-annotations/set-readonly-annotation.cs b/facades-annotations/set-readonly-annotation.cs new file mode 100644 index 00000000..a5a658aa --- /dev/null +++ b/facades-annotations/set-readonly-annotation.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + // Ensure the source PDF exists – create a simple one if it does not. + if (!File.Exists(inputPath)) + { + // Create a new PDF with a single blank page. + using (var tempDoc = new Document()) + { + tempDoc.Pages.Add(); + tempDoc.Save(inputPath); + } + } + + // Load the PDF so we can obtain a Page object – required for the TextAnnotation ctor + Document doc = new Document(inputPath); + Page page = doc.Pages[1]; + + // Define the annotation rectangle (left, bottom, right, top). Adjust as needed. + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 500, 200, 600); + + // Create the TextAnnotation, set visual properties and apply the ReadOnly flag. + TextAnnotation annotation = new TextAnnotation(page, rect) + { + Title = "Note", + Contents = "Read‑only annotation", + Color = Color.Yellow, + Flags = AnnotationFlags.ReadOnly // Apply the read‑only flag before modification + }; + + // Bind the PDF to the annotation editor. + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(inputPath); + + // Apply the annotation to page 1. + editor.ModifyAnnotations(1, 1, annotation); + + // Save the updated PDF. + editor.Save(outputPath); + } +} diff --git a/facades-annotations/skip-flatten-readonly-annotations.cs b/facades-annotations/skip-flatten-readonly-annotations.cs new file mode 100644 index 00000000..cf4ccef4 --- /dev/null +++ b/facades-annotations/skip-flatten-readonly-annotations.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + for (int pageIndex = 1; pageIndex <= doc.Pages.Count; pageIndex++) + { + Page page = doc.Pages[pageIndex]; + for (int annIndex = 1; annIndex <= page.Annotations.Count; annIndex++) + { + Annotation annotation = page.Annotations[annIndex]; + if ((annotation.Flags & AnnotationFlags.ReadOnly) != 0) + { + continue; + } + annotation.Flatten(); + } + } + + doc.Save(outputPath); + } + + Console.WriteLine($"Processed PDF saved to '{outputPath}'."); + } +} diff --git a/facades-annotations/update-annotation-modified-date.cs b/facades-annotations/update-annotation-modified-date.cs new file mode 100644 index 00000000..720a1dc8 --- /dev/null +++ b/facades-annotations/update-annotation-modified-date.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; +using Aspose.Pdf.Facades; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (PdfAnnotationEditor editor = new PdfAnnotationEditor()) + { + // Load the PDF that contains the annotation to be updated + editor.BindPdf(inputPath); + + // Obtain the page object required by the TextAnnotation constructor + Page page = editor.Document.Pages[1]; + // A rectangle must be supplied; its actual values are irrelevant when only the + // Modified date is being updated, so a zero‑size rectangle is used. + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(0, 0, 0, 0); + + // Create the annotation with the required (Page, Rectangle) constructor + TextAnnotation annotation = new TextAnnotation(page, rect) + { + Modified = DateTime.Now // set the modified date to the current system time + }; + + // Apply the modification to annotations on page 1 (start = 1, end = 1) + editor.ModifyAnnotations(1, 1, annotation); + + // Save the updated PDF + editor.Save(outputPath); + Console.WriteLine($"Modified annotation saved to '{outputPath}'."); + } + } +} diff --git a/facades-annotations/validate-no-annotations-after-flattening.cs b/facades-annotations/validate-no-annotations-after-flattening.cs new file mode 100644 index 00000000..eafbbca8 --- /dev/null +++ b/facades-annotations/validate-no-annotations-after-flattening.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Facades; +using Aspose.Pdf.Annotations; + +class Program +{ + static void Main() + { + const string inputPath = "input.pdf"; + const string outputPath = "flattened.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"File not found: {inputPath}"); + return; + } + + using (Document doc = new Document(inputPath)) + { + // Flatten all annotations using the facade + PdfAnnotationEditor editor = new PdfAnnotationEditor(); + editor.BindPdf(doc); + editor.FlatteningAnnotations(); + + // Save the flattened document + doc.Save(outputPath); + + // Verify that no annotations remain in the document structure + bool anyAnnotations = false; + for (int i = 1; i <= doc.Pages.Count; i++) + { + Page page = doc.Pages[i]; + if (page.Annotations.Count > 0) + { + anyAnnotations = true; + break; + } + } + + Console.WriteLine(anyAnnotations ? "Annotations still present after flattening." : "No annotations found after flattening."); + } + } +} \ No newline at end of file diff --git a/facades-annotations/validate-pdf-integrity.cs b/facades-annotations/validate-pdf-integrity.cs new file mode 100644 index 00000000..75a17736 --- /dev/null +++ b/facades-annotations/validate-pdf-integrity.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using Aspose.Pdf; +using Aspose.Pdf.Annotations; + +public class PdfIntegrityValidator +{ + public static bool ValidatePdf(string inputFile, string outputFile) + { + // Load the PDF document + using (Document doc = new Document(inputFile)) + { + // Add a simple text annotation to the first page + Page page = doc.Pages[1]; + Aspose.Pdf.Rectangle rect = new Aspose.Pdf.Rectangle(100, 500, 300, 550); + TextAnnotation annotation = new TextAnnotation(page, rect); + annotation.Title = "Validation Note"; + annotation.Contents = "Annotation added before validation."; + annotation.Color = Aspose.Pdf.Color.Yellow; + page.Annotations.Add(annotation); + + // Save the modified document + doc.Save(outputFile); + + // Validate the document and write log to file + string logFile = "validation.log"; + bool isValid = doc.Validate(logFile, PdfFormat.PDF_A_1B); + + // Return validation result (true = no corrupted objects) + return isValid; + } + } + + // Example usage + public static void Main() + { + string inputPath = "input.pdf"; + string outputPath = "output.pdf"; + + if (!File.Exists(inputPath)) + { + Console.Error.WriteLine($"Input file not found: {inputPath}"); + return; + } + + bool result = ValidatePdf(inputPath, outputPath); + Console.WriteLine($"PDF validation result: {result}"); + } +} \ No newline at end of file diff --git a/facades-annotations/validate-xfdf.cs b/facades-annotations/validate-xfdf.cs new file mode 100644 index 00000000..f3cba4e2 --- /dev/null +++ b/facades-annotations/validate-xfdf.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using System.Xml; +using System.Xml.Schema; +using Aspose.Pdf; + +class Program +{ + static void Main() + { + const string xfdfPath = "form.xfdf"; + const string xsdPath = "xfdf.xsd"; + + if (!File.Exists(xfdfPath)) + { + Console.Error.WriteLine($"XFDF file not found: {xfdfPath}"); + return; + } + + if (!File.Exists(xsdPath)) + { + Console.Error.WriteLine($"XSD schema file not found: {xsdPath}"); + return; + } + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.Schemas.Add(null, xsdPath); + settings.ValidationType = ValidationType.Schema; + settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; + settings.ValidationEventHandler += ValidationCallback; + + using (FileStream xfdfStream = File.OpenRead(xfdfPath)) + using (XmlReader reader = XmlReader.Create(xfdfStream, settings)) + { + try + { + while (reader.Read()) + { + // Reading triggers validation via the settings. + } + Console.WriteLine("XFDF validation completed without errors."); + } + catch (XmlException xmlEx) + { + Console.Error.WriteLine($"XML parsing error: {xmlEx.Message}"); + } + } + } + + private static void ValidationCallback(object sender, ValidationEventArgs e) + { + string severity = e.Severity == XmlSeverityType.Error ? "Error" : "Warning"; + Console.Error.WriteLine($"{severity}: {e.Message}"); + } +} \ No newline at end of file