IRONSOFTWAREHOME
视频

如何在PDF中绘制文本和位图

Curtis Chau
Curtis Chau
Updated: 2026年7月19日

Apache PDFBox 是一个备受推崇的开源 Java 库,用于处理 PDF 文件。 然而,对于 .NET 开发人员来说,可用的选项是非官方的社区驱动移植版本,这些版本带来了重大挑战——Java 风格的 API、不完整的功能覆盖范围以及有限的 .NET 社区支持。 本指南提供了从 Apache PDFBox .NET 移植版到IronPDF的详细迁移路径,IronPDF 是一个专为 .NET 生态系统构建的原生 .NET PDF 库。

为什么考虑从 Apache PDFBox .NET 端口迁移?

虽然 Apache PDFBox 在 Java 生态系统中表现出色,但其非官方的 .NET 移植版本却给 .NET 开发团队带来了一些挑战。

非官方端口状态

Apache PDFBox 主要是一个 Java 库(当前版本 3.0.7,遗留版本 2.0.36,Apache 许可证 2.0)。 所有.NET选项都是社区驱动的移植,大多数已被弃用:Pdfbox 1.1.1(最后发布于2013年,基于PDFBox 1.8.2构建)、Pdfbox-IKVM 1.8.9(最后发布于2017年3月)、PdfBox_DotNet_Version 2.0.15(最后发布于2019年7月)。 唯一积极维护的选项是MASES.NetPDF(3.0.x系列,跟踪PDFBox 3.0.x),这是一个需要JVM在运行时与CLR一起运行的JCOBridge封装。 这些移植通常落后于 Java 版本发布,可能错过关键功能、错误修复或安全更新——这是长生命周期 .NET 项目值得权衡的风险。

Java 优先的 API 设计

移植的应用程序接口保留了 Java 的习惯用法,而这些习惯用法在 .NET 代码中感觉很陌生。 开发者遇到PascalCase,Java IDisposable模式。 这种认知负担会影响开发速度和代码可维护性。

无 HTML 渲染功能

Apache PDFBox 设计用于 PDF 操作,而非 HTML 到 PDF 的转换。 创建 PDF 需要手动构建页面并进行精确的坐标定位--这一过程既繁琐又容易出错,无法满足现代文档生成的需求。

有限的 .NET 社区支持

围绕 Apache PDFBox 端口的 .NET 生态系统非常稀少。 与拥有活跃 .NET 社区的库相比,要找到针对 .NET 问题的帮助、示例或最佳实践非常困难。

JVM 依赖

基于IKVM的移植(MASES.NetPDF通过JCOBridge调用真实的JVM。 无论哪种方式,部署都携带了 Java 运行时的负担,而惯用的 .NET 库则避免。

Apache PDFBox 与 IronPDF:主要区别

了解这些库之间的基本差异有助于规划有效的迁移策略。

方面Apache PDFBox .NET 端口IronPDF
原生设计以 Java 为中心,非官方 .NET 移植本地 .NET 库
API 风格Java约定(close()惯用的C#(using
HTML 渲染不支持(手动构建页面)完全基于 Chromium 的 HTML/CSS/JS
PDF 创建手动坐标定位基于 CSS 的布局
社区以 Java 为重点,.NET 资源稀少活跃的 .NET 社区
支持仅限社区提供商业支持
资源清理明确的close()调用IDisposable与using语句

迁移前准备

前提条件

确保您的环境符合这些要求:

  • .NET Framework 4.6.2+ 或 .NET Core 3.1 / .NET 5-9
  • Visual Studio 2019+ 或 JetBrains Rider
  • 访问 NuGet 包管理器 -IronPDF许可证密钥(可在ironpdf.com免费试用)

审核 Apache PDFBox 的使用情况

在您的解决方案目录中运行这些命令,以识别所有 Apache PDFBox 引用:

grep -r "org.apache.pdfbox\|Org.Apache.Pdfbox\|PDDocument\|PDFTextStripper" --include="*.cs" .
grep -rE "Pdfbox|Pdfbox-IKVM|PdfBox_DotNet_Version|MASES\.NetPDF" --include="*.csproj" .
SHELL

值得期待的重大变化

翻译类别Apache PDFBox .NET 端口IronPDF迁移行动
对象模型PDDocument, PDPagePdfDocument, ChromePdfRenderer不同的类层次结构
PDF 创建手动页面/内容流HTML 渲染重写创建逻辑
方法风格camelCase()(Java风格)PascalCase()(.NET风格)更新方法名称
资源清理document.close()using语句更改处理模式
文件访问Java File对象标准 .NET 字符串/流使用 .NET 类型
文本提取PDFTextStripperpdf.ExtractAllText()更简单的应用程序接口

逐步迁移过程

步骤 1:更新 NuGet 软件包

删除 Apache PDFBox .NET 端口软件包并安装 IronPDF:

# Remove whichever PDFBox .NET port your project uses
dotnet remove package Pdfbox            # built against PDFBox 1.8.2 (2013)
dotnet remove package Pdfbox-IKVM       # IKVM wrapper, last update 2017
dotnet remove package PdfBox_DotNet_Version  # last update 2019
dotnet remove package MASES.NetPDF      # JCOBridge wrapper, requires JVM

# Install IronPDF
dotnet add package IronPdf
SHELL

步骤 2:配置许可证密钥

在应用程序启动时添加IronPDF许可证密钥:

// Add at application startup, before anyIronPDFoperations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

步骤 3:更新命名空间引用

在解决方案中执行全局查找和替换:

所有 PDFBox .NET 移植都镜像 Java 包层次。 基于IKVM的移植保持了Java的小写形式(org.apache.pdfbox.*); Org.Apache.Pdfbox.*)。

查找替换为
using org.apache.pdfbox.pdmodel;(IKVM移植)using IronPdf;
using org.apache.pdfbox.text;(IKVM移植)using IronPdf;
using org.apache.pdfbox.multipdf;(IKVM移植)using IronPdf;
using Org.Apache.Pdfbox.Pdmodel;(MASES.NetPDF)using IronPdf;
using Org.Apache.Pdfbox.Text;(MASES.NetPDF)using IronPdf;

完整的 API 迁移参考

文档操作

Apache PDFBox 方法IronPDF 方法
PDDocument.load(path)PdfDocument.FromFile(path)
PDDocument.load(stream)PdfDocument.FromStream(stream)
new PDDocument()new ChromePdfRenderer()
document.save(path)pdf.SaveAs(path)
document.close()Dispose()
document.getNumberOfPages()pdf.PageCount
document.getPage(index)pdf.Pages[index]
document.removePage(index)pdf.RemovePages(index)

文本提取

Apache PDFBox 方法IronPDF 方法
new PDFTextStripper()不需要
stripper.getText(document)pdf.ExtractAllText()
stripper.setStartPage(n)pdf.Pages[n].Text
stripper.setSortByPosition(true)自动翻译

合并和拆分操作

Apache PDFBox 方法IronPDF 方法
new PDFMergerUtility()不需要
merger.addSource(file)使用FromFile()加载
merger.mergeDocuments()PdfDocument.Merge(pdfs)
new Splitter()不需要
splitter.split(document)pdf.CopyPages(indices)

安全性和加密

Apache PDFBox 方法IronPDF 方法
StandardProtectionPolicypdf.SecuritySettings
policy.setUserPassword()pdf.SecuritySettings.UserPassword
policy.setOwnerPassword()pdf.SecuritySettings.OwnerPassword
policy.setPermissions()pdf.SecuritySettings.AllowUserXxx

代码迁移示例

文本提取

最常见的 Apache PDFBox 操作展示了IronPDF提供的 API 简化功能。

Apache PDFBox .NET 移植实现:

// Apache PDFBox is a Java library — there is no official .NET port.
// Example uses Pdfbox-IKVM (last published 2017) on NuGet; namespaces
// mirror the Java packages exactly because IKVM exposes the Java API.
using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.text;
using java.io;
using System;

class Program
{
    static void Main()
    {
        PDDocument document = PDDocument.load(new File("document.pdf"));
        try
        {
            PDFTextStripper stripper = new PDFTextStripper();
            string text = stripper.getText(document);
            Console.WriteLine(text);
        }
        finally
        {
            document.close();
        }
    }
}

IronPDF 实现:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var pdf = PdfDocument.FromFile("document.pdf");
        string text = pdf.ExtractAllText();
        Console.WriteLine(text);
        
        // Or extract text from specific pages
        string pageText = pdf.ExtractTextFromPage(0);
        Console.WriteLine(pageText);
    }
}

IronPDF完全消除了PDFTextStripper类,用单一方法调用替代了多步骤提取。

HTML 到 PDF 转换

Apache PDFBox 不支持 HTML 到 PDF 的原生转换--这是一个基本的能力差距。

IronPDF 实现:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is HTML to PDF</p>");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}

IronPDF 基于 Chromium 的渲染引擎提供全面的 HTML、CSS 和 JavaScript 支持。 有关高级场景,请参阅 HTML 转 PDF 文档

合并多个 PDF 文件

Apache PDFBox .NET 移植实现:

// Apache PDFBox via a .NET port (e.g. Pdfbox-IKVM on nuget.org).
// The Java class org.apache.pdfbox.multipdf.PDFMergerUtility is exposed
// directly through IKVM, so method names stay Java-style (camelCase).
using org.apache.pdfbox.multipdf;
using org.apache.pdfbox.io;
using System;

class Program
{
    static void Main()
    {
        PDFMergerUtility merger = new PDFMergerUtility();
        merger.addSource("document1.pdf");
        merger.addSource("document2.pdf");
        merger.setDestinationFileName("merged.pdf");
        // MemoryUsageSetting governs heap vs temp-file buffering
        merger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
        Console.WriteLine("PDFs merged");
    }
}

IronPDF 实现:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var pdf1 = PdfDocument.FromFile("document1.pdf");
        var pdf2 = PdfDocument.FromFile("document2.pdf");
        var pdf3 = PdfDocument.FromFile("document3.pdf");
        
        var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
        merged.SaveAs("merged.pdf");
        Console.WriteLine("PDFs merged successfully");
    }
}

IronPDF的静态Merge方法直接接受多个文档,消除了实用类模式。

从零开始创建 PDF 文件

最显著的差异出现在创建 PDF 时。 Apache PDFBox 需要手动进行坐标定位。

Apache PDFBox .NET 移植实现:

using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.pdmodel.font;
using org.apache.pdfbox.pdmodel.edit;

public void CreatePdf(string outputPath)
{
    PDDocument document = new PDDocument();
    try
    {
        PDPage page = new PDPage();
        document.addPage(page);

        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        PDFont font = PDType1Font.HELVETICA_BOLD;

        contentStream.beginText();
        contentStream.setFont(font, 24);
        contentStream.moveTextPositionByAmount(72, 700);
        contentStream.drawString("Hello World");
        contentStream.endText();

        contentStream.beginText();
        contentStream.setFont(PDType1Font.HELVETICA, 12);
        contentStream.moveTextPositionByAmount(72, 650);
        contentStream.drawString("This is a paragraph of text.");
        contentStream.endText();

        contentStream.close();
        document.save(outputPath);
    }
    finally
    {
        document.close();
    }
}

IronPDF 实现:

using IronPdf;

public void CreatePdf(string outputPath)
{
    var renderer = new ChromePdfRenderer();

    string html = @"
        <html>
        <head>
            <style>
                body { font-family: Helvetica, Arial, sans-serif; margin: 1in; }
                h1 { font-size: 24pt; font-weight: bold; }
                p { font-size: 12pt; }
            </style>
        </head>
        <body>
            <h1>Hello World</h1>
            <p>This is a paragraph of text.</p>
        </body>
        </html>";

    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs(outputPath);
}

基于 HTML/CSS 的创建无需进行坐标计算、字体管理和内容流操作。

添加密码保护

Apache PDFBox .NET 移植实现:

using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.pdmodel.encryption;

public void ProtectPdf(string inputPath, string outputPath, string password)
{
    PDDocument document = PDDocument.load(new File(inputPath));
    try
    {
        AccessPermission ap = new AccessPermission();
        ap.setCanPrint(true);
        ap.setCanExtractContent(false);

        StandardProtectionPolicy spp = new StandardProtectionPolicy(password, password, ap);
        spp.setEncryptionKeyLength(128);

        document.protect(spp);
        document.save(outputPath);
    }
    finally
    {
        document.close();
    }
}

IronPDF 实现:

using IronPdf;

public void ProtectPdf(string inputPath, string outputPath, string password)
{
    using var pdf = PdfDocument.FromFile(inputPath);

    pdf.SecuritySettings.UserPassword = password;
    pdf.SecuritySettings.OwnerPassword = password;
    pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
    pdf.SecuritySettings.AllowUserCopyPasteContent = false;

    pdf.SaveAs(outputPath);
}

IronPDF 使用强类型属性,而不是单独的权限和策略对象。

添加水印

Apache PDFBox .NET 移植实现:

using org.apache.pdfbox.pdmodel;
using org.apache.pdfbox.pdmodel.edit;
using org.apache.pdfbox.pdmodel.font;

public void AddWatermark(string inputPath, string outputPath, string watermarkText)
{
    PDDocument document = PDDocument.load(new File(inputPath));
    try
    {
        PDFont font = PDType1Font.HELVETICA_BOLD;

        for (int i = 0; i < document.getNumberOfPages(); i++)
        {
            PDPage page = document.getPage(i);
            PDPageContentStream cs = new PDPageContentStream(
                document, page, PDPageContentStream.AppendMode.APPEND, true, true);

            cs.beginText();
            cs.setFont(font, 72);
            cs.setNonStrokingColor(200, 200, 200);
            cs.setTextMatrix(Matrix.getRotateInstance(Math.toRadians(45), 200, 400));
            cs.showText(watermarkText);
            cs.endText();
            cs.close();
        }

        document.save(outputPath);
    }
    finally
    {
        document.close();
    }
}

IronPDF 实现:

using IronPdf;

public void AddWatermark(string inputPath, string outputPath, string watermarkText)
{
    using var pdf = PdfDocument.FromFile(inputPath);

    pdf.ApplyWatermark(
        $"<h1 style='color:lightgray;font-size:72px;'>{watermarkText}</h1>",
        rotation: 45,
        opacity: 50);

    pdf.SaveAs(outputPath);
}

IronPDF基于 HTML 的水印功能消除了页面迭代和矩阵计算。

URL到PDF转换

Apache PDFBox 不支持 URL 到 PDF 的转换。IronPDF提供本地支持:

using IronPdf;

public void ConvertUrlToPdf(string url, string outputPath)
{
    var renderer = new ChromePdfRenderer();
    using var pdf = renderer.RenderUrlAsPdf(url);
    pdf.SaveAs(outputPath);
}

有关完整的 URL 转换选项,请参阅 URL 转 PDF 文档

页眉和页脚

Apache PDFBox 要求在每个页面上手动定位,不支持内置页眉/页脚。IronPDF提供声明式配置:

using IronPdf;

public void CreatePdfWithHeaderFooter(string html, string outputPath)
{
    var renderer = new ChromePdfRenderer();

    renderer.RenderingOptions.TextHeader = new TextHeaderFooter
    {
        CenterText = "Document Title",
        FontSize = 12
    };

    renderer.RenderingOptions.TextFooter = new TextHeaderFooter
    {
        CenterText = "Page {page} of {total-pages}",
        FontSize = 10
    };

    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs(outputPath);
}

有关高级布局,请参阅页眉和页脚文档

ASP.NET Core 集成

IronPDF 可与现代 .NET 网络应用程序自然集成:

[HttpPost]
public IActionResult GeneratePdf([FromBody] ReportRequest request)
{
    var renderer = new ChromePdfRenderer();
    using var pdf = renderer.RenderHtmlAsPdf(request.Html);

    return File(pdf.BinaryData, "application/pdf", "report.pdf");
}

同步支持

Apache PDFBox 端口不支持异步操作。IronPDF提供完整的Async/Await功能:

using IronPdf;

public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}

依赖注入配置

public interface IPdfService
{
    Task<byte[]> GeneratePdfAsync(string html);
    string ExtractText(string pdfPath);
}

public class IronPdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;

    public IronPdfService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
    }

    public async Task<byte[]> GeneratePdfAsync(string html)
    {
        using var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
        return pdf.BinaryData;
    }

    public string ExtractText(string pdfPath)
    {
        using var pdf = PdfDocument.FromFile(pdfPath);
        return pdf.ExtractAllText();
    }
}

性能优化

内存使用对比

情景Apache PDFBox .NET 端口IronPDF
文本提取~80 MB~50 MB
PDF 创建~100 MB~60 MB
批量(100 份 PDF)高(人工清理)~100 MB

优化技巧

使用using语句:

//自动翻译cleanup with IDisposable pattern
using var pdf = PdfDocument.FromFile(path);

批量操作重用渲染器:

var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs($"output_{i}.pdf");
}

在 Web 应用程序中使用 Async:

using var pdf = await renderer.RenderHtmlAsPdfAsync(html);

常见迁移问题的故障排除

问题:未找到 Java 风格方法名称

PascalCase .NET等价物替换camelCase Java方法:

// PDFBox: stripper.getText(document)
// IronPDF: pdf.ExtractAllText()

// PDFBox: document.getNumberOfPages()
// IronPDF: pdf.PageCount

问题:没有close()方法

IronPDF使用了IDisposable模式:

// PDFBox
document.close();

// IronPDF
using var pdf = PdfDocument.FromFile(path);
//自动翻译disposal at end of scope

问题:没有PDFTextStripper等效物

文本提取简化为一种方法:

// IronPDF: Just call ExtractAllText()
string text = pdf.ExtractAllText();

// Per-page extraction:
string pageText = pdf.Pages[0].Text;

问题:PDFMergerUtility未找到

使用静态Merge方法:

//IronPDFuses static Merge
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);

迁移后核对表

完成代码迁移后,请验证以下内容:

  • 运行所有现有的单元测试和集成测试
  • 将 PDF 输出结果与以前的版本进行直观比较
  • 测试文本提取准确率
  • 验证许可证是否正常工作(IronPdf.License.IsLicensed
  • 与先前实现的性能基准测试
  • 更新 CI/CD 流水线依赖项
  • 为您的开发团队记录新的模式

其他资源


从 Apache PDFBox .NET 移植到IronPDF可将您的 PDF 代码库从 Java 风格模式转换为成语 C#。 从手动坐标定位到 HTML/CSS 渲染的转变,再加上本地异步支持和现代 .NET 集成,为您的生产应用程序提供了更简洁、更易维护的代码和专业支持。

请注意: Apache PDFBox 是其各自所有者的注册商标。 本网站与Apache软件基金会没有关联、没有得到其认可或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户