c# pdf 页面计数 – 使用 GroupDocs.Annotation 提取文档信息

介绍

是否曾经盯着一堆文档发呆,想知道它们到底包含什么而不必逐个打开?你并非唯一面临这种困境的人。无论你是在构建文档管理系统、处理法律文件,还是仅仅想整理公司数字资产,了解如何 extract document information in C#——包括 c# pdf page count——都可能成为改变游戏规则的关键。

手动检查文件属性既耗时又容易出错。借助 GroupDocs.Annotation for .NET,你可以自动化整个过程,仅用几行代码即可获取文件类型、页数、文档大小等信息。本教程将展示此功能的重要性、如何设置库以及即开即用的逐步代码示例。

快速答案

  • GroupDocs.Annotation 能提取什么? 文件类型、页数、大小以及基本元数据。
  • 支持多少种格式? 超过 50 种输入和输出格式,包括 PDF、DOCX、XLSX、PPTX 和常见图像类型。
  • 是否可以在不加载整个文件的情况下获取 c# pdf 页面计数? 可以——GetDocumentInfo() 只读取获取页数所需的头部信息。
  • 开发时需要许可证吗? 免费试用可用于测试;生产环境需要完整许可证。
  • API 对 Web 应用是否线程安全? 绝对安全——只需正确释放 Annotator 实例。

什么是 c# pdf 页面计数?

c# pdf 页面计数 是通过 API 查询 PDF 文件时返回的总页数。使用 GroupDocs.Annotation,你可以通过 GetDocumentInfo() 方法瞬间获取该值,而无需渲染整个文档。该计数来源于 PDF 的内部结构,帮助你在不打开文件查看器的情况下决定处理、存储或显示方式。它在批量验证、合规检查和 UI 预览(需要限制页数)时尤为有用。

为什么使用 GroupDocs.Annotation 提取文档信息?

GroupDocs.Annotation 支持 50+ 文档格式,能够在不将整个文件加载到内存的情况下处理数百页的文件,在普通服务器上可在 200 ms 以下返回元数据。这种速度和格式覆盖范围使其非常适合大规模自动化、合规检查和智能内容分类。

先决条件和设置

您需要的内容

  • Visual Studio 2019 或更高版本(Community 版完全可用)
  • .NET Framework 4.6.1+ 或 .NET Core 2.0+
  • 基础 C# 知识并熟悉 NuGet

安装 GroupDocs.Annotation

将库引入项目非常简单。请选择你喜欢的方式:

选项 1:Package Manager Console(推荐)

Install-Package GroupDocs.Annotation -Version 25.4.0

选项 2:.NET CLI

dotnet add package GroupDocs.Annotation --version 25.4.0

选项 3:Package Manager UI
如果你更喜欢点击而不是敲命令,只需在 NuGet 包管理器 UI 中搜索 “GroupDocs.Annotation”,然后安装最新版本。

获取许可证

  1. Start with the Free Trial: Download from the GroupDocs website – no strings attached.
  2. Need More Time? Get a temporary license for extended evaluation.
  3. Ready to Go Live? Purchase a full license when you’re ready to deploy.

Pro tip: 免费试用会添加水印,但足以用于学习和测试代码。

欲了解最新更改,请参阅 release notes。

如何使用 GroupDocs.Annotation 获取 c# pdf 页面计数?

Annotator 是用于加载文档并提供注释及元数据功能的主要类。
使用 new Annotator("file.pdf") 加载 PDF 并调用 GetDocumentInfo() ——PageCount 属性在仅两行代码内返回精确的页数。GetDocumentInfo() 返回一个 DocumentInfo 对象,包含页数、文件类型和大小等元数据。该方法仅读取必要的头部数据,即使是大型 PDF 也能高效处理。

基本设置和文档加载

using System;
using GroupDocs.Annotation;

class Program
{
    static void Main(string[] args)
    {
        // Initialize the annotator with a document path
        using (Annotator annotator = new Annotator("YOUR_DOCUMENT_DIRECTORY/input.pdf"))
        {
            Console.WriteLine("Document loaded successfully!");
            // We'll add the extraction code here next
        }
    }
}

提取文档元数据

using (Annotator annotator = new Annotator("YOUR_DOCUMENT_DIRECTORY/input.pdf"))
{
    // Extract document info
    IDocumentInfo info = annotator.Document.GetDocumentInfo();
    
    // Always check if info was retrieved successfully
    if (info == null || info.PageCount == 0)
    {
        throw new Exception("Unexpected document information!");
    }

    // Display the extracted information
    Console.WriteLine($"\
File type: {info.FileType}\
Number of pages: {info.PageCount}\
Document size: {info.Size} bytes.");
    
    // Convert size to more readable format
    string readableSize = FormatFileSize(info.Size);
    Console.WriteLine($"Document size (formatted): {readableSize}");
}

// Helper method to format file size
static string FormatFileSize(long bytes)
{
    string[] suffixes = { "B", "KB", "MB", "GB", "TB" };
    int counter = 0;
    decimal number = bytes;
    
    while (Math.Round(number / 1024) >= 1)
    {
        number /= 1024;
        counter++;
    }
    
    return string.Format("{0:n1}{1}", number, suffixes[counter]);
}

DocumentInfo 封装了文件的提取属性,便于在应用程序中读取和使用。

增强信息显示

using (Annotator annotator = new Annotator("YOUR_DOCUMENT_DIRECTORY/input.pdf"))
{
    IDocumentInfo info = annotator.Document.GetDocumentInfo();
    
    if (info == null)
    {
        Console.WriteLine("Could not retrieve document information.");
        return;
    }

    // Comprehensive info display
    Console.WriteLine("=== Document Information ===");
    Console.WriteLine($"File Type: {info.FileType}");
    Console.WriteLine($"Page Count: {info.PageCount}");
    Console.WriteLine($"Size: {FormatFileSize(info.Size)}");
    
    // Additional checks you might want to perform
    if (info.PageCount > 100)
    {
        Console.WriteLine("⚠️  Large document detected - consider batch processing");
    }
    
    if (info.Size > 10 * 1024 * 1024) // 10MB
    {
        Console.WriteLine("⚠️  Large file size - may impact processing time");
    }
    
    Console.WriteLine("=== Analysis Complete ===");
}

如果需要更多上下文——例如文档是否超过大小阈值——可以在基础示例上加入额外检查和业务逻辑。

常见问题和解决方案

问题 1:“文件未找到”错误

Direct answer: 验证文件路径是绝对路径或正确相对于应用程序基目录,并确保进程拥有读取权限。

string documentPath = @"C:\Documents\test.pdf";

// Always check if file exists first
if (!File.Exists(documentPath))
{
    Console.WriteLine($"File not found: {documentPath}");
    return;
}

try
{
    using (Annotator annotator = new Annotator(documentPath))
    {
        // Your code here
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error loading document: {ex.Message}");
}

问题 2:不受支持的文件格式

Direct answer: 确认文件扩展名属于 50+ 支持的格式之一;如果不在支持范围内,请先转换为受支持的类型再调用 GetDocumentInfo()。

try
{
    using (Annotator annotator = new Annotator(documentPath))
    {
        IDocumentInfo info = annotator.Document.GetDocumentInfo();
        
        if (info == null)
        {
            Console.WriteLine("Unsupported file format or corrupted document");
            return;
        }
        
        // Process the info
    }
}
catch (UnsupportedFileTypeException ex)
{
    Console.WriteLine($"File type not supported: {ex.Message}");
}

问题 3:大型文档的内存问题

Direct answer: 在加载前实现大小检查,并使用 using 语句确保 Annotator 实例被及时释放,以防止内存泄漏。

const long MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB limit

FileInfo fileInfo = new FileInfo(documentPath);
if (fileInfo.Length > MAX_FILE_SIZE)
{
    Console.WriteLine("File too large for processing");
    return;
}

// Use proper disposal patterns
using (Annotator annotator = new Annotator(documentPath))
{
    // Process quickly and dispose
    IDocumentInfo info = annotator.Document.GetDocumentInfo();
    // Handle info immediately
}
// Annotator is automatically disposed here

真实场景使用案例

文档管理系统集成

当用户上传文件时,首先提取其元数据,以决定存储位置、索引策略或所需的审批工作流。

public class DocumentProcessor
{
    public DocumentMetadata ProcessUpload(string filePath)
    {
        using (Annotator annotator = new Annotator(filePath))
        {
            IDocumentInfo info = annotator.Document.GetDocumentInfo();
            
            return new DocumentMetadata
            {
                FileName = Path.GetFileName(filePath),
                FileType = info.FileType.ToString(),
                PageCount = info.PageCount,
                FileSizeBytes = info.Size,
                ProcessedDate = DateTime.UtcNow,
                Category = DetermineCategory(info)
            };
        }
    }
    
    private string DetermineCategory(IDocumentInfo info)
    {
        // Business logic for automatic categorization
        if (info.FileType.ToString().Contains("Pdf"))
        {
            return info.PageCount > 20 ? "Legal Document" : "Standard Document";
        }
        
        return "Other";
    }
}

批量文档分析

在后台任务中处理文件夹中的所有文件,记录每个文档的页数和类型,以便生成报告。

public void AnalyzeDocumentFolder(string folderPath)
{
    string[] supportedExtensions = { ".pdf", ".docx", ".xlsx", ".pptx" };
    
    foreach (string file in Directory.GetFiles(folderPath))
    {
        if (!supportedExtensions.Contains(Path.GetExtension(file).ToLower()))
            continue;
            
        try
        {
            using (Annotator annotator = new Annotator(file))
            {
                IDocumentInfo info = annotator.Document.GetDocumentInfo();
                Console.WriteLine($"{Path.GetFileName(file)}: {info.FileType}, {info.PageCount} pages");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Failed to process {file}: {ex.Message}");
        }
    }
}

合规性和验证

受监管行业常要求文档的页数或大小必须在一定范围内。利用提取的元数据可自动拒绝不合规的上传。

public bool ValidateDocument(string filePath, DocumentRequirements requirements)
{
    using (Annotator annotator = new Annotator(filePath))
    {
        IDocumentInfo info = annotator.Document.GetDocumentInfo();
        
        // Check file type
        if (requirements.AllowedTypes != null && 
            !requirements.AllowedTypes.Contains(info.FileType.ToString()))
        {
            return false;
        }
        
        // Check page count limits
        if (info.PageCount < requirements.MinPages || 
            info.PageCount > requirements.MaxPages)
        {
            return false;
        }
        
        // Check file size
        if (info.Size > requirements.MaxSizeBytes)
        {
            return false;
        }
        
        return true;
    }
}

性能优化技巧

1. 实现缓存

为频繁访问的文件缓存 DocumentInfo 结果,避免重复的 I/O 操作。

private static readonly Dictionary<string, IDocumentInfo> _infoCache = 
    new Dictionary<string, IDocumentInfo>();

public IDocumentInfo GetDocumentInfoCached(string filePath)
{
    string fileHash = GetFileHash(filePath);
    
    if (_infoCache.ContainsKey(fileHash))
    {
        return _infoCache[fileHash];
    }
    
    using (Annotator annotator = new Annotator(filePath))
    {
        IDocumentInfo info = annotator.Document.GetDocumentInfo();
        _infoCache[fileHash] = info;
        return info;
    }
}

2. 为多个文档使用异步处理

利用 Task.Run 或异步流并发处理大量文件,避免阻塞主线程。

public async Task<List<DocumentMetadata>> ProcessDocumentsAsync(string[] filePaths)
{
    var tasks = filePaths.Select(async path =>
    {
        return await Task.Run(() =>
        {
            using (Annotator annotator = new Annotator(path))
            {
                IDocumentInfo info = annotator.Document.GetDocumentInfo();
                return new DocumentMetadata(path, info);
            }
        });
    });
    
    return (await Task.WhenAll(tasks)).ToList();
}

3. 内存管理最佳实践

  • 始终在 using 块中包装 Annotator。
  • 分批处理文档,而不是一次性全部加载。
  • 对于大于 100 MB 的文件,考虑先将文件流式写入磁盘,再读取元数据。

故障排除指南

许可证相关问题

License 是将你的产品激活文件注册到 GroupDocs 库的对象。确保许可证文件放置在应用程序根文件夹,并在任何其他 GroupDocs 调用之前实例化 License 对象。

// Set license before using any GroupDocs functionality
License license = new License();
license.SetLicense("path/to/your/license.lic");

// Or use stream for embedded licenses
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("YourApp.license.lic"))
{
    license.SetLicense(stream);
}

性能问题

Direct answer: 对应用进行性能分析,将文件大小限制在 100 MB 以内以实现实时处理,并为重复读取启用缓存。

平台特定问题

Direct answer: 使用 Path.Combine 构建跨平台路径;Windows 使用反斜杠,Linux 使用正斜杠。

// Use Path.Combine for cross-platform compatibility
string documentPath = Path.Combine(baseDirectory, "documents", fileName);

处理受密码保护的文档

Direct answer: 在创建 Annotator 实例时传入密码,或在调用 GetDocumentInfo() 前通过 LoadOptions 设置密码。

LoadOptions loadOptions = new LoadOptions() { Password = "your-password" };
using (Annotator annotator = new Annotator("protected-document.pdf", loadOptions))
{
    // Extract information normally
}

更新 GroupDocs.Annotation

Direct answer: 运行 dotnet add package GroupDocs.Annotation --version <latest> 或使用 NuGet 包管理器 UI 拉取最新版本。

Update-Package GroupDocs.Annotation

常见问题

Q: GroupDocs.Annotation 支持哪些文档格式用于信息提取?
A: GroupDocs.Annotation 支持超过 50 种文档格式,包括 PDF、DOCX、XLSX、PPTX、JPEG、PNG、TIFF、CAD 文件等。

Q: 我可以提取自定义元数据或属性吗?
A: GetDocumentInfo() 提供文件类型、页数、大小等核心元数据。若需作者、创建日期等自定义属性,可结合 GroupDocs.Annotation 与 GroupDocs.Metadata,或使用原生文件格式的属性 API。

Q: 如何处理受密码保护的文档?
A: 在创建 Annotator 实例时提供密码,例如 new Annotator("secure.pdf", new LoadOptions { Password = "pwd" })。

Q: 是否有办法在不将整个文件加载到内存的情况下提取文档信息?
A: 有——GetDocumentInfo() 只读取文件头部,即使是数百页的 PDF 也能保持低内存占用。

Q: 我可以在 Web 应用或多线程环境中使用吗?
A: 完全可以。GroupDocs.Annotation 是线程安全的,只需为每个请求创建新的 Annotator 并及时释放即可。

结论与后续步骤

你现在已经掌握了一套完整、可投入生产的方案,使用 GroupDocs.Annotation 提取 c# pdf 页面计数、文件类型和大小。你已经了解了库的设置、元数据检索、常见陷阱以及大规模场景下的性能优化。

后续操作:

  1. 克隆示例项目并使用真实文件运行提供的占位代码。
  2. 探索 GroupDocs.Annotation 的其他功能,如注释渲染和文档比较。
  3. 将元数据提取集成到现有的上传流水线,实现自动分类和验证。

记住,可靠的文档处理始于准确的元数据。借助 GroupDocs.Annotation,你可以构建更智能、更快速、更具可扩展性的解决方案。


Last Updated: 2026-06-01
Tested With: GroupDocs.Annotation 25.4.0 (latest)
Author: GroupDocs

重要链接:

相关教程