IRONSOFTWAREHOME
影片

如何在 PDF 上畫文字和位圖

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

Apache PDFBox是一個備受尊敬的開源Java程式庫,用於處理PDF。 然而,對於.NET開發者來說,現有的選擇是非官方的社群驅動移植,這帶來了重大挑戰—Java風格的API、不完整的功能覆蓋以及有限的.NET社群支援。 本指南提供了從Apache PDFBox .NET移植到IronPDF的詳細遷移路徑,這是一個專為.NET生態系統構建的原生.NET PDF程式庫。

為什麼考慮從Apache PDFBox .NET移植遷移?

雖然Apache PDFBox在Java生態系統中表現傑出,但其非官方的.NET移植存在多種挑戰,影響.NET開發團隊的工作。

非官方移植狀態

Apache PDFBox主要是Java程式庫(當前版本3.0.7,遺留版本2.0.36,Apache License 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),這是一個JCOBridge包裝,需要在運行時與CLR一起使用JVM。 這些移植通常落後於Java的版本,可能缺少關鍵功能、錯誤修復或安全更新—這是值得權衡的長期.NET專案風險。

Java首選API設計

移植的API保留了Java慣例,這在.NET程式碼中顯得不熟悉。 開發者會遇到PascalCase,Java IDisposable模式。 這種認知開銷影響開發速度和程式碼的可維護性。

不支援HTML渲染功能

Apache PDFBox的設計是為了進行PDF操作,不是HTML到PDF轉換。 建立PDF需要手動構建頁面並進行精確的座標定位—這是一個乏味且易出錯的過程,無法適應現代文件生成的需求。

有限的.NET社群支援

圍繞Apache PDFBox移植的.NET生態系統非常稀少。 相比於擁有活躍.NET社群的程式庫,尋求針對.NET特定問題的幫助、範例或最佳實踐顯得困難。

JVM相依性

基於IKVM的移植(Pdfbox-IKVM, Pdfbox)捆綁了一個.NET JVM的重新實現,而MASES.NetPDF通過JCOBridge調用一個真正的JVM。 無論哪種方式,部署都攜帶Java運行時包袱,這是典型的.NET程式庫所避免的。

Apache PDFBox vs. IronPDF: 主要差異

了解這些程式庫之間的基本差異,有助於制定有效的遷移策略。

方面Apache PDFBox .NET移植IronPDF
原生設計以Java為中心,非官方.NET移植原生.NET程式庫
API風格Java慣例(camelCase, close()典型的C#(PascalCase, using
HTML渲染不支援(手動頁面構建)完整的基於Chromium的HTML/CSS/JS
PDF建立手動坐標定位基於 CSS 的佈局
社群以Java為中心,稀少的.NET資源活躍的.NET社群
支援僅限社群支援提供商業支援
資源清理顯式close()調用IDiposable與using語句

遷移前準備

前提條件

確保您的環境符合以下要求:

  • .NET Framework 4.6.2+ or .NET Core 3.1 / .NET 5-9
  • Visual Studio 2019+ or 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()更簡單的API

逐步遷移過程

步驟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 web應用程式整合:

[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提供了完整的非同步/等待功能:

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 PDFs)高(手動清理)~100 MB

優化提示

使用using語句:

//自動cleanup with IDisposable pattern
using var pdf = PdfDocument.FromFile(path);
C#

重用渲染器進行批量操作:

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

在 Web 應用中使用異步:

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

故障排除常見的遷移問題

問題:未找到Java風格的方法名稱

camelCase Java方法替換為PascalCase .NET等效方法:

// 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
C#

問題:沒有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 Software Foundation無關,並未獲得其認可或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供參考,反映撰寫時公開可用的資訊。
Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

...
閱讀更多

相關文章

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天試用金鑰
無需信用卡或帳戶建立