如何在 .NET 中清除 PDF 文件的批註
當 PDF 中充斥著審閱者的評論、標記與標註時,文件很快就會變得難以閱讀。無論您是在準備法律簡報、最終研究論文,或是企業報告,通常都需要在發布或存檔前 清除批註。在本教學中,您將學會如何使用 GroupDocs.Annotation for .NET 清除 PDF 批註、為何此函式庫優於其他方案,以及如何處理常見的陷阱。
快速解答
- 刪除所有 PDF 批註的最快方法是什麼? 呼叫
annotator.Save(outputPath, new SaveOptions { AnnotationTypes = AnnotationType.None })。 - 開始使用是否需要授權? 不需要 – 免費試用版可用於開發與小規模測試。
- 支援哪些 .NET 版本? .NET Framework 4.5+、.NET Core 3.1+、.NET 5/6/7。
- 可以保持原始檔案不變嗎? 可以 – API 總是寫入全新清潔檔案,來源檔案保持完整。
- GroupDocs.Annotation 支援多少種檔案格式? 超過 50 種輸入與輸出格式,包括 PDF、DOCX、XLSX、PPTX 以及各類影像。
什麼是「清除批註」?
清除批註 指以程式方式移除 PDF 中的每一個批註物件,使最終檔案僅保留原始內容與版面配置。此操作會產生一個沒有批註層的全新 PDF,並保留頁面順序、字型與內嵌影像。
為何使用 GroupDocs.Annotation for .NET?
GroupDocs.Annotation 支援 50+ 檔案格式,且可在不將整份文件載入記憶體的情況下處理高達 200 MB 的 PDF,提供記憶體效能佳的解決方案,適合多執行緒環境。相較於一般 PDF 函式庫,它內建批註類型過濾、批次處理,且在清理後保留原始版面的正確率達 99.9 %。
前置條件
- GroupDocs.Annotation .NET 函式庫(v25.4.0 或更新版)
- Visual Studio(任意版本)或其他相容 .NET 的 IDE
- 基本的 C# 語法與
using陳述式概念 - 一個包含至少一個批註的範例 PDF(可使用 Adobe Acrobat、Foxit,或免費的 Edge PDF 檢視器加入批註)
設定 GroupDocs.Annotation
安裝(簡易方式)
選項 1:NuGet 套件管理員主控台
Install-Package GroupDocs.Annotation -Version 25.4.0
選項 2:.NET CLI(如果您偏好指令列)
dotnet add package GroupDocs.Annotation --version 25.4.0
處理授權問題
您可以先使用 免費試用,在投入正式環境時再切換至永久授權。
基本設定(前五行程式碼)
Annotator 類別是代表已載入記憶體的 PDF 文件的入口點,提供讀取、編輯與儲存批註的方法。
using GroupDocs.Annotation;
string sourceDocumentPath = "YOUR_DOCUMENT_DIRECTORY/ANNOTATED";
using (Annotator annotator = new Annotator(sourceDocumentPath))
{
// Your annotation removal magic happens here
}
專業提示:
using陳述式會自動釋放Annotator實例,關閉檔案句柄,避免在大量檔案迴圈處理時產生記憶體洩漏。
如何使用 GroupDocs.Annotation 清除 PDF 中的所有批註?
SaveOptions 類別讓您自訂文件的儲存方式,包括保留或捨棄哪些批註類型。AnnotationType 為列舉,列出所有支援的批註類別,如 Highlight、Comment、Strikeout 等。
載入來源 PDF 後,將 SaveOptions.AnnotationTypes 設為 AnnotationType.None,再呼叫 annotator.Save(outputPath, saveOptions)。此單行指令會移除整個批註層,保留原始文字、影像與版面,並將清潔的 PDF 寫入指定位置,且不會修改來源檔案。
annotator.Save(resultFilePath, new SaveOptions { AnnotationTypes = AnnotationType.None });
主要步驟:逐步移除批註
理解問題
清除批註會產生一個 全新 PDF 版本,其中不再包含批註物件。此舉會產生以下可量化的效益:
- 檔案大小縮減 – 清理後通常減少 5‑15 % 的容量。
- 完整性保留 – 頁面順序、字型與影像保持完全不變。
- 中繼資料移除 – 所有與批註相關的中繼資料皆被剔除。
- 不影響原檔 – 原始檔案保持不變,對於稽核追蹤相當重要。
步驟 1:正確設定檔案路徑(正確做法)
正確的路徑處理可避免最常見的「找不到檔案」錯誤。Path.Combine 會產生跨平台的路徑字串,讓相同程式碼在 Windows、macOS 與 Linux 上皆可執行。
inputFilePath 變數保存帶批註的 PDF 位置,resultFilePath 則指向清潔 PDF 的輸出位置。
using System.IO;
string documentDirectory = "YOUR_DOCUMENT_DIRECTORY";
string outputDirectory = "YOUR_OUTPUT_DIRECTORY";
// Define paths for source and result documents
string annotatedPdfPath = Path.Combine(documentDirectory, "ANNOTATED");
string resultFilePath = Path.Combine(outputDirectory, "result.pdf");
為何使用 Path.Combine? 它會自動插入正確的目錄分隔符(
\或/),避免因雙分隔符導致的執行時例外。
步驟 2:載入文件
Annotator 類別是 GroupDocs.Annotation 的核心物件,負責解析 PDF 並公開其批註集合。
using GroupDocs.Annotation;
using GroupDocs.Annotation.Options;
using (Annotator annotator = new Annotator(annotatedPdfPath))
{
// The next step happens here
}
背後運作原理: 當您實例化
Annotator時,函式庫會串流檔案、在記憶體中建立每個批註的表示,並為後續修改做好準備。對於超過 100 MB 的 PDF,此步驟可能需要數秒鐘。
步驟 3:魔法一行(移除全部批註)
以下這行程式碼即可清除所有批註並寫入清潔檔案:
annotator.Save(resultFilePath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
annotator.Save– 依目前狀態寫出新 PDF。new SaveOptions()– 讓您調整儲存流程;預設設定已能滿足大多數情境。AnnotationTypes = AnnotationType.None– 關鍵旗標,告訴引擎省略所有批註物件。
替代做法(僅移除特定類型)
若您想保留評論但捨棄標記,可使用位元 OR 組合欲排除的類型。
// Remove only highlights and text annotations, keep others
annotator.Save(resultFilePath, new SaveOptions() {
AnnotationTypes = AnnotationType.Highlight | AnnotationType.Text
});
完整範例程式碼
以下方法示範了完整的端對端清理流程,您可以直接嵌入任何 .NET 主控台或 Web 專案中使用。
using System.IO;
using GroupDocs.Annotation;
using GroupDocs.Annotation.Options;
public void RemoveAllAnnotations()
{
string documentDirectory = "YOUR_DOCUMENT_DIRECTORY";
string outputDirectory = "YOUR_OUTPUT_DIRECTORY";
string annotatedPdfPath = Path.Combine(documentDirectory, "ANNOTATED");
string resultFilePath = Path.Combine(outputDirectory, "result.pdf");
using (Annotator annotator = new Annotator(annotatedPdfPath))
{
annotator.Save(resultFilePath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
}
Console.WriteLine($"Clean document saved to: {resultFilePath}");
}
疑難排解:當問題發生時
如何修復「找不到檔案」錯誤?
在建立 Annotator 前先驗證來源 PDF 是否存在,這樣可避免建構子拋出例外。
if (!File.Exists(annotatedPdfPath))
{
throw new FileNotFoundException($"Source document not found: {annotatedPdfPath}");
}
如何處理「未找到批註」的結果?
先檢查批註計數。若文件確實沒有批註,清理步驟會產生與原檔相同的副本。
using (Annotator annotator = new Annotator(annotatedPdfPath))
{
var annotations = annotator.Get();
Console.WriteLine($"Found {annotations.Count} annotations");
if (annotations.Count == 0)
{
Console.WriteLine("No annotations to remove");
return;
}
// Proceed with removal...
}
如何提升大型檔案的效能?
處理 150 頁、數百筆批註的 PDF 可能會佔用大量記憶體。可採用批次處理、提升應用程式記憶體上限,或以非同步方式執行。
// For multiple files, process asynchronously
public async Task ProcessMultipleFiles(string[] filePaths)
{
var tasks = filePaths.Select(async filePath =>
{
await Task.Run(() => RemoveAnnotationsFromFile(filePath));
});
await Task.WhenAll(tasks);
}
真實情境應用
法律文件準備
律師事務所常收到帶有多筆審閱意見的合約。提交法院前,必須在保留法律條文與頁碼的前提下,將所有標記全部剔除。
專業提示: 先將原始帶批註的版本存檔以符合法規要求,清潔版才是提交用的最終文件。
學術出版
研究人員在稿件上會留下大量同行評審意見。期刊要求提交乾淨的手稿,您可以在投稿前自動移除高亮、評論與便利貼。
企業報告最終化
執行摘要會經歷多輪審閱。向利害關係人展示的最終 PDF 必須去除內部評論,以維持專業形象。
內容管理系統
若您建置文件入口網站,可提供「審閱模式」顯示批註,與「發布模式」隱藏批註。上述程式碼可即時產生乾淨副本,實現無縫切換。
進階技巧與最佳化
選擇性批註移除
有時只需要刪除特定類型的批註(例如高亮)。AnnotationTypes 屬性接受多個旗標的組合。
// Remove only highlights and strikethrough, keep comments
var saveOptions = new SaveOptions()
{
AnnotationTypes = AnnotationType.Highlight | AnnotationType.Strikeout
};
annotator.Save(resultFilePath, saveOptions);
批次處理多個文件
當資料夾內有數十個帶批註的 PDF 時,可迴圈遍歷每個檔案,套用相同的清理邏輯,並記錄處理結果。
public void CleanAllDocumentsInFolder(string inputFolder, string outputFolder)
{
var pdfFiles = Directory.GetFiles(inputFolder, "*.pdf");
foreach (var file in pdfFiles)
{
var fileName = Path.GetFileName(file);
var outputPath = Path.Combine(outputFolder, $"clean_{fileName}");
using (var annotator = new Annotator(file))
{
annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
}
Console.WriteLine($"Processed: {fileName}");
}
}
大型文件的記憶體最佳化
對於超過 200 MB 的 PDF,請監控記憶體使用量,並在每個檔案處理完畢後呼叫 GC.Collect() 以釋放非受控資源。
public void ProcessLargeDocument(string inputPath, string outputPath)
{
GC.Collect(); // Clean up before starting
using (var annotator = new Annotator(inputPath))
{
var initialMemory = GC.GetTotalMemory(false);
annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
var finalMemory = GC.GetTotalMemory(false);
Console.WriteLine($"Memory used: {(finalMemory - initialMemory) / 1024 / 1024} MB");
}
GC.Collect(); // Clean up after processing
}
生產環境的最佳實踐
如何實作健全的錯誤處理?
捕捉特定例外、記錄詳細資訊,並在發生錯誤時繼續處理其他檔案,而非中斷整個批次。
try
{
using (var annotator = new Annotator(inputPath))
{
annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"Input file not found: {ex.Message}");
// Log the error, notify user, etc.
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"Permission denied: {ex.Message}");
// Handle permission issues
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex.Message}");
// Log full exception details
}
如何安全管理設定?
將檔案路徑、授權金鑰與其他設定存於 appsettings.json 或環境變數中,避免硬編碼於程式碼。
// In appsettings.json
{
"DocumentSettings": {
"InputDirectory": "C:\\Documents\\Input",
"OutputDirectory": "C:\\Documents\\Output",
"BackupOriginals": true
}
}
// In your code
var config = Configuration.GetSection("DocumentSettings");
var inputDir = config["InputDirectory"];
var outputDir = config["OutputDirectory"];
如何加入日誌與監控?
整合 ILogger 或第三方監控服務(如 Serilog、Application Insights),以捕捉處理時間、成功率與記憶體消耗等指標。
public void RemoveAnnotationsWithLogging(string inputPath, string outputPath)
{
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
try
{
using (var annotator = new Annotator(inputPath))
{
var annotationCount = annotator.Get().Count;
Console.WriteLine($"Processing {inputPath} - Found {annotationCount} annotations");
annotator.Save(outputPath, new SaveOptions() { AnnotationTypes = AnnotationType.None });
stopwatch.Stop();
Console.WriteLine($"Successfully processed in {stopwatch.ElapsedMilliseconds}ms");
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to process {inputPath}: {ex.Message}");
throw;
}
}
接下來該做什麼?
現在您已能可靠地 清除 PDF 批註,可以將工作流程延伸至:
- 建置自動化文件審閱管線,將帶批註與清潔版本同時存檔。
- 與 SharePoint 或其他 DMS 平台整合,強制執行清潔副本政策。
- 開發 UI 工具,讓最終使用者在移除前先預覽批註。
兩行程式碼的簡易清理,加上 GroupDocs.Annotation 強大的格式支援,使此方案成為任何需要維持文件純淨的企業的理想選擇。
常見問與答
問:我可以移除除 PDF 之外的其他檔案類型的批註嗎?
答:可以。GroupDocs.Annotation 亦支援 Word、Excel、PowerPoint 與影像格式;只要更換輸入檔案副檔名,即可使用相同的 API 呼叫。
問:移除批註會改變原始版面嗎?
答:不會。函式庫僅移除批註層,文字、影像與頁面結構皆保持不變。
問:如何只刪除特定類型的批註?
答:將 AnnotationTypes 設為欲排除類型的位元組合,例如 AnnotationType.Highlight | AnnotationType.Strikeout。
問:此程序會修改來源 PDF 嗎?
答:不會。原始檔案永遠不會被覆寫,清潔的 PDF 會寫入您在 Save 中指定的路徑。
問:效能會隨文件大小如何變化?
答:對於最高 200 MB 的 PDF,清理通常在標準 2.5 GHz CPU 上於 5 秒內完成。更大的檔案建議使用批次處理與非同步執行以提升效能。
其他資源
- GroupDocs.Annotation 文件 – 完整 API 參考與進階教學
- GroupDocs.Annotation API 參考 – 方法逐項說明
- 下載最新版本 – 取得最新發行版,包含錯誤修正與效能提升
- 購買方案 – 開發、測試與正式環境的授權方案
最後更新: 2026-06-01
測試環境: GroupDocs.Annotation 25.4.0 for .NET
作者: GroupDocs