Cara Menandai PDF dengan GroupDocs Annotation .NET (C#)

Pernah membutuhkan cara menandai pdf file secara programatis dan bertanya-tanya pustaka mana yang memberi Anda kekuatan sekaligus kesederhanaan? Baik Anda membangun platform tinjauan hukum, sistem e‑learning, atau alur kerja dokumen kolaboratif, GroupDocs.Annotation .NET menyediakan API siap produksi yang memungkinkan Anda menambah, mengedit, dan menghapus anotasi PDF langsung dari kode C#. Dalam panduan ini Anda akan mempelajari semua yang diperlukan untuk mengimplementasikan mesin anotasi lengkap, mulai dari penyiapan awal hingga penyetelan kinerja untuk perpustakaan dokumen yang besar.

Jawaban Cepat

  • Apa cara tercepat untuk menambahkan catatan teks ke PDF? Muat dokumen dengan Annotator, buat TextAnnotation, atur Box dan Message‑nya, lalu panggil Add() – semua dalam kurang dari satu detik untuk halaman tipikal.
  • Versi .NET apa yang didukung? .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5, .NET 6, dan .NET 7.
  • Apakah saya memerlukan lisensi untuk produksi? Ya – lisensi penuh atau sementara menghapus watermark dan membuka semua fitur.
  • Bisakah saya memproses PDF 200‑halaman pada server 4 GB? Ya, dengan menggunakan pemrosesan batch dan pola pembuangan yang tepat seperti yang ditunjukkan nanti.
  • Apakah GroupDocs.Annotation cocok untuk anotasi dokumen hukum? Tentu – mendukung lebih dari 50 format, kontrol izin granular, dan metadata siap audit.

Apa itu “cara menandai pdf”?

“Cara menandai pdf” mengacu pada proses menambahkan markup secara programatis—seperti komentar, sorotan, bentuk, atau redaksi—ke file PDF. Dengan menggunakan GroupDocs.Annotation .NET, Anda dapat mengotomatisasi alur kerja ini, menyimpan data anotasi di basis data, dan menampilkan hasil secara instan di penampil web atau desktop.

Mengapa menggunakan GroupDocs.Annotation untuk markup PDF?

GroupDocs.Annotation mendukung lebih dari 50 format input dan output, dapat menangani PDF hingga 500 MB tanpa memuat seluruh file ke memori, dan menyediakan operasi thread‑safe ketika setiap permintaan membuat instance Annotator sendiri. Dibandingkan dengan pustaka yang lebih ringan dan hanya PDF, ia juga memungkinkan Anda menandai file Word, PowerPoint, dan gambar menggunakan API yang sama, yang secara dramatis mengurangi upaya pengembangan untuk platform multi‑format.

Aplikasi Dunia Nyata: Di Mana Anotasi Dokumen Bersinar

Memahami konteks bisnis membantu Anda memilih jenis anotasi yang tepat.

  • Peninjauan Dokumen Hukum – Pengacara menambahkan komentar, menyorot klausul, dan melampirkan riwayat revisi. GroupDocs.Annotation melacak setiap perubahan dengan ID pengguna, cap waktu, dan tanda tangan digital opsional untuk kepatuhan audit.
  • Platform Pendidikan – Instruktur dapat menilai tugas dengan menggambar bentuk, menambahkan catatan tempel, atau menyematkan umpan balik audio langsung pada PDF siswa.
  • Dokumentasi Kesehatan – Klinisi menandai laporan radiologi atau bagan pasien sambil mempertahankan metadata yang sesuai dengan HIPAA.
  • Dokumentasi Perangkat Lunak – Penulis teknis berkolaborasi pada spesifikasi API, menyisipkan kotak penjelasan dan catatan revisi tanpa meninggalkan PDF sumber.
  • Layanan Keuangan – Petugas kepatuhan menandai perjanjian pinjaman, penilaian risiko, dan jejak audit, kemudian mengekspor versi beranotasi untuk arsip.

Prasyarat dan Penyiapan: Menyiapkan Lingkungan Anda

Persyaratan Sistem

  • IDE: Visual Studio 2019 atau yang lebih baru (edisi Community sudah cukup).
  • Runtime: .NET Framework 4.6.1+ atau .NET Core 2.0+ (disarankan 8 GB RAM untuk PDF besar).
  • Izin: Akses menulis ke folder tempat PDF beranotasi akan disimpan.

Prasyarat Pengetahuan

  • Sintaks dasar C# dan konsep berorientasi objek.
  • Familiaritas dengan manajemen paket NuGet.
  • Pemahaman tentang I/O file (membaca/menulis aliran).

Menginstal GroupDocs.Annotation .NET

Anda dapat menambahkan pustaka melalui NuGet. Pilih metode yang sesuai dengan alur kerja Anda.

Menggunakan NuGet Package Manager Console

Install-Package GroupDocs.Annotation -Version 25.4.0

Menggunakan .NET CLI (direkomendasikan untuk pipeline CI/CD)

dotnet add package GroupDocs.Annotation --version 25.4.0

Pro Tip: Selalu pin versi (mis., Install-Package GroupDocs.Annotation -Version 23.12). Ini mencegah perubahan yang merusak secara tidak sengaja ketika paket diperbarui secara otomatis. Lihat rilis terbaru di GroupDocs releases page.

Opsi Lisensi: Pilih yang Sesuai untuk Proyek Anda

  • Uji Coba Gratis – Fungsi penuh dengan watermark evaluasi selama 30 hari.
  • Lisensi Sementara – Menghapus watermark selama 30 hari, ideal untuk proof‑of‑concept. Lihat halaman lisensi sementara.
  • Lisensi Penuh – Penggunaan produksi tak terbatas, dukungan prioritas, dan tanpa watermark. Beli melalui GroupDocs store.

Penyiapan Proyek Dasar

Buat proyek konsol C# baru atau proyek ASP.NET dan tambahkan pernyataan using berikut setelah menginstal paket:

using GroupDocs.Annotation;
using GroupDocs.Annotation.Models;
using GroupDocs.Annotation.Models.AnnotationModels;
using System.IO;
using System.Collections.Generic;

// Initialize Annotator with an input document path
string inputPath = Path.Combine("YOUR_DOCUMENT_DIRECTORY", "sample.pdf");

Important: Ganti YOUR_DOCUMENT_DIRECTORY dengan jalur absolut ke PDF Anda. Menggunakan Path.Combine menjamin pemisah jalur yang benar di Windows dan Linux.

Tutorial Langkah‑per‑Langkah: Menambahkan Anotasi Pertama Anda

Bagaimana cara memuat dokumen PDF untuk anotasi?

Kelas Annotator adalah komponen inti yang memuat dokumen dan mengelola semua operasi anotasi. Memuat PDF dengan benar memastikan pustaka dapat membaca dimensi halaman, metadata, dan anotasi yang ada sebelum perubahan apa pun diterapkan.
Muat PDF dengan konstruktor Annotator, memberikan jalur file dan opsi pemuatan opsional. Langkah ini memvalidasi file dan menyiapkan representasi dalam memori yang dapat Anda modifikasi dengan aman, sekaligus menangani file terenkripsi jika kata sandi disediakan.

try 
{
    using (Annotator annotator = new Annotator(inputPath))
    {
        // Your annotation code goes here
        Console.WriteLine("Document loaded successfully!");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error loading document: {ex.Message}");
}

Blok try‑catch melindungi dari file yang hilang, PDF yang rusak, atau format yang tidak didukung, memastikan aplikasi Anda gagal dengan elegan alih‑alih crash.

Bagaimana cara menambahkan anotasi teks ke PDF?

TextAnnotation mewakili komentar bergaya catatan tempel yang dapat ditempatkan pada halaman PDF. Menambahkannya melibatkan pembuatan objek, menentukan lokasinya, mengatur pesan yang ditampilkan, dan akhirnya menyisipkannya ke dokumen melalui Annotator.
Buat objek TextAnnotation, tentukan persegi pembatasnya dengan properti Box, atur Message yang terlihat, dan kemudian panggil Add() pada Annotator. Anotasi muncul secara instan pada halaman yang ditentukan, dan Anda dapat menyesuaikan tampilannya dengan pengaturan warna dan opasitas jika diperlukan.

// Create a highlight annotation
HighlightAnnotation highlight = new HighlightAnnotation
{
    Box = new Rectangle(100, 100, 200, 20), // x, y, width, height
    CreatedOn = DateTime.Now,
    Message = "This section needs review",
    Replies = new List<Reply>
    {
        new Reply
        {
            Comment = "Please verify these numbers",
            RepliedOn = DateTime.Now
        }
    }
};

// Add the annotation to the document
annotator.Add(highlight);

Mengapa properti Box penting: Persegi menggunakan satuan point (1 point = 1/72 inci) yang diukur dari sudut kiri bawah halaman. Koordinat yang tepat memungkinkan Anda menempatkan catatan tepat di mana reviewer mengharapkannya.

Bagaimana cara menyimpan PDF beranotasi tanpa menimpa sumber?

Menyimpan ke file baru mempertahankan dokumen asli untuk jejak audit dan skenario rollback. Metode Save menulis semua perubahan, termasuk anotasi baru dan metadata, ke jalur yang ditentukan sambil membiarkan sumber tidak tersentuh.
Panggil Save() pada Annotator dan berikan jalur file baru. Ini mempertahankan dokumen asli, yang penting untuk jejak audit dan rollback, dan Anda dapat secara opsional menentukan format output yang berbeda jika konversi diperlukan.

string outputPath = Path.Combine("YOUR_OUTPUT_DIRECTORY", "annotated_document.pdf");
annotator.Save(outputPath);
Console.WriteLine($"Document saved to: {outputPath}");

Best Practice: Simpan versi asli dan beranotasi di folder terkontrol versi terpisah. Strategi ini menyederhanakan kepatuhan regulasi dan pelacakan perubahan.

Teknik Anotasi Lanjutan

Bagaimana cara menambahkan beberapa jenis anotasi dalam satu operasi?

GroupDocs.Annotation menawarkan serangkaian kelas anotasi yang kaya—HighlightAnnotation, StrikeoutAnnotation, PolylineAnnotation, RedactionAnnotation, dan lainnya. Dengan membuat setiap instance, mengonfigurasi propertinya, dan menambahkannya ke Annotator yang sama sebelum menyimpan, Anda meminimalkan I/O dan menjaga keadaan dokumen tetap konsisten.
Instansiasi setiap jenis anotasi, atur atribut spesifiknya (warna, opasitas, titik, dll.), dan tambahkan secara berurutan ke instance Annotator yang sama. Saat Anda memanggil Save(), semua anotasi ditulis bersama, memastikan pembaruan atomik dan mengurangi kemungkinan penulisan parsial.

// Text annotation for comments
TextAnnotation textNote = new TextAnnotation
{
    Box = new Rectangle(300, 200, 100, 30),
    Message = "Review required",
    CreatedOn = DateTime.Now,
    FontColor = 16711680, // Red color in RGB
    BackgroundColor = 16777215 // White background
};

// Arrow annotation to point out specific elements
ArrowAnnotation pointer = new ArrowAnnotation
{
    Box = new Rectangle(150, 150, 50, 50),
    Message = "Important calculation here",
    CreatedOn = DateTime.Now
};

// Add all annotations at once
annotator.Add(textNote);
annotator.Add(pointer);

Bagaimana cara memperbarui warna atau komentar anotasi yang ada?

Metode GetById mengambil anotasi tertentu berdasarkan pengenal uniknya, memungkinkan Anda memodifikasi hanya bidang yang diperlukan. Setelah mengambil objek, Anda dapat mengubah properti seperti Color atau Message dan kemudian menyimpan perubahan dengan Update.
Ambil anotasi berdasarkan Id uniknya menggunakan GetById(), ubah properti yang diinginkan (mis., Color, Message), dan panggil Update(). Pendekatan ini menghindari pembuatan ulang anotasi dan mempertahankan posisi asli, riwayat versi, serta balasan yang terlampir.

// Get all annotations from the document
List<AnnotationBase> annotations = annotator.Get();

// Find and update a specific annotation
foreach (var annotation in annotations)
{
    if (annotation.Message.Contains("Review required"))
    {
        annotation.Message = "Review completed ✓";
        annotator.Update(annotation);
        break;
    }
}

Performance Note: Untuk dokumen dengan ribuan anotasi, cache ID anotasi dalam kamus untuk menghindari pencarian linear.

Masalah Umum dan Pemecahan Masalah

Masalah 1 – “Format dokumen tidak didukung”

Direct Answer: Verifikasi bahwa ekstensi file muncul dalam daftar format yang didukung oleh GroupDocs.Annotation; jika tidak, konversi file ke PDF terlebih dahulu atau gunakan produk GroupDocs lain yang menangani format tersebut.
Solution:

// Check if format is supported before processing
string extension = Path.GetExtension(inputPath).ToLower();
if (extension != ".pdf" && extension != ".docx" && extension != ".pptx")
{
    throw new NotSupportedException($"File format {extension} is not supported");
}

Masalah 2 – Anotasi muncul di posisi yang salah

Direct Answer: Pastikan Anda menggunakan sistem koordinat yang benar (asal di kiri‑bawah) dan metadata rotasi halaman dihormati. Sesuaikan nilai Box sesuai.

// Always validate coordinates before adding annotations
private bool IsValidCoordinate(Rectangle box, double pageWidth, double pageHeight)
{
    return box.X >= 0 && box.Y >= 0 && 
           (box.X + box.Width) <= pageWidth && 
           (box.Y + box.Height) <= pageHeight;
}

Masalah 3 – Masalah memori dengan dokumen besar

Direct Answer: Proses PDF besar secara batch, buang (dispose) Annotator setelah setiap batch, dan aktifkan mode streaming untuk menghindari memuat seluruh file ke RAM.
Solution:

// Process large documents in chunks
using (Annotator annotator = new Annotator(inputPath))
{
    // Set memory-friendly options
    LoadOptions loadOptions = new LoadOptions
    {
        PreviewPageCount = 1 // Load pages on demand
    };
    
    // Process annotations in batches
    const int batchSize = 10;
    for (int i = 0; i < annotations.Count; i += batchSize)
    {
        var batch = annotations.Skip(i).Take(batchSize);
        foreach (var annotation in batch)
        {
            annotator.Add(annotation);
        }
        
        // Force garbage collection between batches for large documents
        if (i % 50 == 0)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }
}

Tips Optimasi Kinerja

Bagaimana cara memproses ribuan PDF secara batch dengan efisien?

Kumpulkan permintaan anotasi ke dalam daftar, buka satu Annotator per dokumen, terapkan semua perubahan, kemudian panggil Save() sekali. Ini mengurangi overhead I/O, memanfaatkan buffering internal, dan menjaga penggunaan memori dapat diprediksi pada beban kerja besar.
Kumpulkan permintaan anotasi ke dalam daftar, buka satu Annotator per dokumen, terapkan semua perubahan, kemudian panggil Save() sekali. Ini mengurangi overhead I/O dan memanfaatkan buffering internal.

// Inefficient approach (don't do this)
foreach (var annotation in annotations)
{
    annotator.Add(annotation);
    annotator.Save(outputPath); // Saving after each annotation is expensive
}

// Efficient approach
foreach (var annotation in annotations)
{
    annotator.Add(annotation);
}
annotator.Save(outputPath); // Save once at the end

Bagaimana cara mengelola memori saat bekerja dengan PDF ber‑ratus halaman?

Aktifkan flag LoadOptions MemoryOptimization = true dan proses halaman secara berurutan. Ini memberi tahu pustaka untuk hanya menyimpan halaman aktif di memori, secara dramatis mengurangi jejak RAM untuk file yang sangat besar.

// Use using statements to ensure proper disposal
using (var annotator = new Annotator(inputPath))
{
    // Your annotation code here
} // Annotator is automatically disposed, freeing memory

Bagaimana seharusnya saya cache dokumen yang sering diakses?

Simpan JSON anotasi yang diserialisasi dalam cache terdistribusi (mis., Redis) dengan kunci ID dokumen. Ketika pengguna meminta PDF yang sama, ambil set anotasi yang di‑cache alih‑alih membaca ulang file dari disk, mengurangi latensi dan beban I/O.

// Cache document metadata to avoid reloading
private static readonly Dictionary<string, DocumentInfo> _documentCache = 
    new Dictionary<string, DocumentInfo>();

private DocumentInfo GetDocumentInfo(string path)
{
    if (!_documentCache.ContainsKey(path))
    {
        using (var annotator = new Annotator(path))
        {
            _documentCache[path] = annotator.GetDocumentInfo();
        }
    }
    return _documentCache[path];
}

Praktik Terbaik untuk Aplikasi Produksi

Bagaimana cara mengimplementasikan penanganan error dan logging yang kuat?

Bungkus setiap operasi Annotator dalam blok try‑catch, catat pengecualian dengan logger terstruktur (Serilog, NLog), dan sertakan jalur dokumen, ID pengguna, serta stack trace. Ini membuat pemecahan masalah jauh lebih mudah di produksi dan membantu Anda memenuhi persyaratan audit kepatuhan.

public async Task<bool> AddAnnotationSafely(string documentPath, AnnotationBase annotation)
{
    try
    {
        using (var annotator = new Annotator(documentPath))
        {
            annotator.Add(annotation);
            annotator.Save(documentPath.Replace(".pdf", "_annotated.pdf"));
            return true;
        }
    }
    catch (Exception ex)
    {
        // Log the error (use your preferred logging framework)
        Console.WriteLine($"Annotation failed for {documentPath}: {ex.Message}");
        return false;
    }
}

Bagaimana cara memvalidasi data anotasi yang diberikan pengguna?

Periksa bahwa bidang JSON yang masuk (nomor halaman, koordinat persegi, tipe anotasi) berada dalam rentang yang dapat diterima sebelum membuat objek anotasi. Tolak koordinat di luar batas dengan respons HTTP 400 yang jelas dan berikan pesan error yang membantu.

public bool ValidateAnnotationInput(AnnotationBase annotation)
{
    if (annotation == null)
        return false;
    
    if (string.IsNullOrWhiteSpace(annotation.Message))
        return false;
    
    if (annotation.Box.Width <= 0 || annotation.Box.Height <= 0)
        return false;
    
    return true;
}

Bagaimana cara memastikan keamanan thread dalam layanan web multi‑pengguna?

Instansiasi Annotator baru per permintaan; jangan pernah berbagi satu instance di antara thread. Jika Anda perlu mengoordinasikan akses ke file bersama, gunakan SemaphoreSlim atau kunci tingkat file untuk mencegah penulisan bersamaan.

private readonly object _annotationLock = new object();

public void AddAnnotationThreadSafe(string documentPath, AnnotationBase annotation)
{
    lock (_annotationLock)
    {
        using (var annotator = new Annotator(documentPath))
        {
            annotator.Add(annotation);
            annotator.Save(documentPath);
        }
    }
}

Kapan Menggunakan GroupDocs.Annotation vs. Alternatif

Pilih GroupDocs.Annotation ketika Anda membutuhkan:

  • Dukungan lintas format (PDF, DOCX, PPTX, gambar).
  • Jenis anotasi lanjutan seperti redaksi, gambar bebas, dan metadata khusus.
  • Lisensi tingkat perusahaan, dukungan ber‑SLA, dan pembaruan keamanan reguler.

Pertimbangkan alternatif yang lebih ringan ketika Anda hanya bekerja dengan PDF, memiliki batasan anggaran ketat, atau memerlukan stack open‑source.

Pertanyaan yang Sering Diajukan

Q: Bisakah saya menggunakan GroupDocs.Annotation .NET tanpa lisensi?
A: Ya, uji coba gratis menyediakan fungsi penuh selama 30 hari tetapi menambahkan watermark evaluasi pada setiap file output. Untuk setiap penyebaran produksi Anda harus menerapkan lisensi sementara atau penuh untuk menghapus watermark tersebut.

Q: Versi .NET apa yang didukung oleh GroupDocs.Annotation?
A: Pustaka ini bekerja dengan .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5, .NET 6, dan .NET 7, menjadikannya cocok untuk layanan Windows warisan serta kontainer lintas‑platform modern.

Q: Berapa biaya GroupDocs.Annotation .NET?
A: Harga mulai sekitar $1,999 untuk lisensi pengembang dan meningkat sesuai jumlah aplikasi yang disebarkan. Lihat halaman harga GroupDocs untuk tarif terbaru dan diskon volume.

Q: Format dokumen apa yang dapat saya anotasi dengan GroupDocs.Annotation?
A: Lebih dari 50 format didukung, termasuk PDF, DOC/DOCX, PPT/PPTX, XLS/XLSX, JPEG, PNG, TIFF, dan banyak lagi. PDF menerima set fitur paling komprehensif, termasuk bentuk berbasis vektor dan redaksi siap OCR.

Q: Bisakah saya menandai PDF yang dilindungi kata sandi?
A: Ya. Berikan kata sandi saat membuat Annotator:

LoadOptions loadOptions = new LoadOptions { Password = "your_password" };
using (Annotator annotator = new Annotator(inputPath, loadOptions))
{
    // Your annotation code here
}

Q: Mengapa anotasi saya muncul di posisi yang salah?
A: GroupDocs menggunakan sistem koordinat Kartesius di mana (0,0) adalah sudut kiri‑bawah dan pengukuran dalam point. Posisi yang salah biasanya berasal dari penggunaan nilai berbasis piksel atau mengabaikan rotasi halaman. Konversi nilai piksel ke point (1 pixel ≈ 0,75 point pada 96 DPI) dan sesuaikan dengan metadata rotasi apa pun.

// Correct approach - validate coordinates
private bool ValidateCoordinates(Rectangle box, double pageWidth, double pageHeight)
{
    return box.X >= 0 && box.Y >= 0 && 
           (box.X + box.Width) <= pageWidth && 
           (box.Y + box.Height) <= pageHeight;
}

Q: Bagaimana cara mengambil anotasi yang ada dari PDF?
A: Panggil metode Get() pada instance Annotator; ia mengembalikan koleksi semua objek anotasi dengan ID, tipe, dan metadata mereka.

using (Annotator annotator = new Annotator(inputPath))
{
    List<AnnotationBase> annotations = annotator.Get();
    foreach (var annotation in annotations)
    {
        Console.WriteLine($"Annotation: {annotation.Message}");
    }
}

Q: Bisakah saya menghapus anotasi tertentu secara programatis?
A: Ya. Gunakan Delete(id) untuk menghapus satu anotasi atau DeleteAll() untuk mengosongkan seluruh dokumen. Anda juga dapat memfilter berdasarkan tipe sebelum penghapusan.

List<AnnotationBase> annotationsToDelete = annotator.Get()
    .Where(a => a.Message.Contains("obsolete"))
    .ToList();

foreach (var annotation in annotationsToDelete)
{
    annotator.Remove(annotation);
}

Q: Bagaimana cara memperbarui properti anotasi seperti warna atau pesan?
A: Ambil anotasi, ubah Color atau Message, lalu panggil Update(). Perubahan disimpan pada pemanggilan Save() berikutnya.

var annotations = annotator.Get();
var targetAnnotation = annotations.FirstOrDefault(a => a.Id == specificId);
if (targetAnnotation != null)
{
    targetAnnotation.Message = "Updated message";
    annotator.Update(targetAnnotation);
}

Q: Bisakah saya menambahkan metadata khusus ke anotasi?
A: Tentu. Sebagian besar kelas anotasi menyediakan koleksi Replies dimana Anda dapat menyimpan pasangan kunci‑nilai, memungkinkan Anda melampirkan ID reviewer, cap waktu, atau status alur kerja.

var annotation = new HighlightAnnotation
{
    // ... other properties
    Replies = new List<Reply>
    {
        new Reply
        {
            Comment = "Custom metadata: priority=high, category=legal",
            RepliedOn = DateTime.Now
        }
    }
};

Q: Apakah GroupDocs.Annotation mendukung tanda tangan digital pada PDF beranotasi?
A: Meskipun pustaka Annotation berfokus pada markup, Anda dapat menggabungkannya dengan GroupDocs.Signature .NET untuk menerapkan tanda tangan kriptografis setelah anotasi ditambahkan, memastikan integritas visual dan legal.

Q: Bisakah saya mengekspor anotasi ke JSON atau XML untuk pemrosesan eksternal?
A: Pustaka tidak menyertakan pengekspor bawaan, tetapi Anda dapat menyerialisasi objek anotasi sendiri menggunakan System.Text.Json atau XmlSerializer. Ini memudahkan integrasi dengan sistem audit eksternal.

List<AnnotationBase> annotations = annotator.Get();
string jsonAnnotations = JsonConvert.SerializeObject(annotations, Formatting.Indented);
File.WriteAllText("annotations.json", jsonAnnotations);

Terakhir Diperbarui: 2026-05-21
Diuji Dengan: GroupDocs.Annotation 23.12 untuk .NET
Penulis: GroupDocs

Tutorial Terkait