Cómo migrar de Apache PDFBox a IronPDF
Apache PDFBox es una respetada biblioteca Java de código abierto para gestionar archivos PDF. Sin embargo, para los desarrolladores de .NET , las opciones disponibles son puertos no oficiales impulsados por la comunidad que plantean desafíos importantes: API de estilo Java, cobertura de funciones incompleta y soporte limitado de la comunidad .NET . Esta guía proporciona una ruta de migración detallada desde los puertos Apache PDFBox .NET a IronPDF, una biblioteca PDF .NET nativa creada específicamente para el ecosistema .NET .
¿Por qué considerar migrar desde los puertos Apache PDFBox .NET ?
Si bien Apache PDFBox es excelente en el ecosistema Java, sus puertos .NET no oficiales presentan varios desafíos que afectan a los equipos de desarrollo .NET .
Estado no oficial del puerto
Apache PDFBox es principalmente una biblioteca Java. Todas las versiones de .NET son ports impulsados por la comunidad que carecen de soporte oficial por parte del proyecto Apache. Estos puertos a menudo van a la zaga de las versiones de Java y pueden carecer de características críticas, correcciones de errores o actualizaciones de seguridad. Para los equipos que crean aplicaciones con requisitos de longevidad que se extienden hasta 2025 y 2026, esta incertidumbre crea un riesgo técnico.
Diseño de API Java-First
Las API portadas conservan las convenciones de Java que resultan extrañas en el código .NET. Los desarrolladores encuentran métodos camelCase en lugar de PascalCase, objetos Java File en lugar de cadenas .NET estándar y llamadas close() explícitas en lugar de patrones IDisposable. Esta sobrecarga cognitiva afecta la velocidad de desarrollo y la capacidad de mantenimiento del código.
Sin capacidad de renderizado HTML
Apache PDFBox está diseñado para la manipulación de PDF, no para la conversión de HTML a PDF. La creación de archivos PDF requiere la construcción manual de páginas con un posicionamiento preciso de las coordenadas, un proceso tedioso y propenso a errores que no se adapta a las necesidades modernas de generación de documentos.
Asistencia limitada de la comunidad .NET
El ecosistema .NET en torno a los puertos Apache PDFBox es escaso. Encontrar ayuda, ejemplos o mejores prácticas para cuestiones específicas de .NET resulta difícil en comparación con las bibliotecas con comunidades activas de .NET.
Potenciales dependencias de JVM
Algunos puertos de Apache PDFBox pueden requerir componentes de ejecución Java, lo que añade complejidad a la implantación y gestión del entorno en infraestructuras centradas en .NET.
Apache PDFBox frente a IronPDF: Diferencias clave
Comprender las diferencias fundamentales entre estas bibliotecas ayuda a planificar una estrategia de migración eficaz.
| Aspecto | Puertos .NET de Apache PDFBox | IronPDF |
|---|---|---|
| Diseño nativo | Versión no oficial de .NET centrada en Java | .NET nativo, con soporte profesional |
| Estilo API | Convenciones de Java (camelCase, close()) |
C# idiomático (PascalCase, using) |
| Representación HTML | No compatible (construcción manual de la página) | HTML/CSS/JS completo basado en Chromium |
| Creación de PDF | Posicionamiento manual por coordenadas | Maquetación basada en CSS |
| Comunidad | Centrado en Java, escasos recursos .NET | Comunidad .NET activa, más de 10 millones de descargas |
| Soporte | Sólo para la comunidad | Asistencia profesional disponible |
| Limpieza de recursos | Llamadas explícitas close() |
IDisposable con declaraciones using |
Preparación de la migración
Prerrequisitos
Asegúrese de que su entorno cumple estos requisitos:
- .NET Framework 4.6.2+ o .NET Core 3.1 / .NET 5-9
- Visual Studio 2019+ o JetBrains Rider
- Acceso al gestor de paquetes NuGet
- Clave de licencia deIronPDF(prueba gratuita disponible en ironpdf.com)
Auditar el uso de Apache PDFBox
Ejecute estos comandos en su directorio de soluciones para identificar todas las referencias a Apache PDFBox:
grep -r "apache.pdfbox\|PdfBox\|PDDocument\|PDFTextStripper" --include="*.cs" .
grep -r "PdfBox\|Apache.PdfBox" --include="*.csproj" .
grep -r "apache.pdfbox\|PdfBox\|PDDocument\|PDFTextStripper" --include="*.cs" .
grep -r "PdfBox\|Apache.PdfBox" --include="*.csproj" .
Cambios importantes que hay que anticipar
| Categoría | Puerto .NET de Apache PDFBox | IronPDF | Acción de migración |
|---|---|---|---|
| Modelo de objeto | PDDocument, PDPage |
PdfDocument, ChromePdfRenderer |
Diferente jerarquía de clases |
| Creación de PDF | Secuencias manuales de páginas/contenido | Traducción HTML | Reescribir la lógica de creación |
| Estilo del método | camelCase() (estilo Java) |
PascalCase() (estilo .NET ) |
Actualizar nombres de métodos |
| Limpieza de recursos | document.close() |
using declaraciones |
Cambiar el patrón de eliminación |
| Acceso a archivos | Objetos Java File |
Cadenas y secuencias .NET Standard | Utilizar tipos de .NET |
| Extracción de Texto | PDFTextStripper clase |
pdf.ExtractAllText() |
API más sencilla |
Proceso de migración paso a paso
Paso 1: Actualizar paquetes NuGet
Elimine los paquetes del puerto .NET de Apache PDFBox e instale IronPDF:
# Remove PDFBox .NET port packages
dotnet remove package PdfBox
dotnet remove package PDFBoxNet
dotnet remove package Apache.PdfBox
# Install IronPDF
dotnet add package IronPdf
# Remove PDFBox .NET port packages
dotnet remove package PdfBox
dotnet remove package PDFBoxNet
dotnet remove package Apache.PdfBox
# Install IronPDF
dotnet add package IronPdf
Paso 2: Configurar la clave de licencia
Añada la clave de licencia deIronPDFal iniciar la aplicación:
// Add at application startup, before anyIronPDFoperations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup, before anyIronPDFoperations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup, before any IronPDF operations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
Paso 3: Actualizar referencias de espacios de nombres
Realice una búsqueda y sustitución global en toda la solución:
| Visite | Sustituir por |
|---|---|
using org.apache.pdfbox.pdmodel; |
using IronPdf; |
using org.apache.pdfbox.text; |
using IronPdf; |
using org.apache.pdfbox.multipdf; |
using IronPdf; |
using PdfBoxDotNet.Pdmodel; |
using IronPdf; |
using Apache.Pdfbox.PdModel; |
using IronPdf; |
Referencia completa de migración de API
Operaciones de documentos
| Método Apache PDFBox | Método 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() |
Declaración using o Dispose() |
document.getNumberOfPages() |
pdf.PageCount |
document.getPage(index) |
pdf.Pages[index] |
document.removePage(index) |
pdf.RemovePages(index) |
Extracción de texto
| Método Apache PDFBox | Método IronPDF |
|---|---|
new PDFTextStripper() |
No es necesario |
stripper.getText(document) |
pdf.ExtractAllText() |
stripper.setStartPage(n) |
pdf.Pages[n].Text |
stripper.setSortByPosition(true) |
Automático |
Operaciones de fusión y división
| Método Apache PDFBox | Método IronPDF |
|---|---|
new PDFMergerUtility() |
No es necesario |
merger.addSource(file) |
Cargar con FromFile() |
merger.mergeDocuments() |
PdfDocument.Merge(pdfs) |
new Splitter() |
No es necesario |
splitter.split(document) |
pdf.CopyPages(indices) |
Seguridad y cifrado
| Método Apache PDFBox | Método IronPDF |
|---|---|
StandardProtectionPolicy |
pdf.SecuritySettings |
policy.setUserPassword() |
pdf.SecuritySettings.UserPassword |
policy.setOwnerPassword() |
pdf.SecuritySettings.OwnerPassword |
policy.setPermissions() |
pdf.SecuritySettings.AllowUserXxx |
Ejemplos de migración de código
Extracción de texto
La operación más común de Apache PDFBox demuestra la simplificación de la API que proporciona IronPDF.
Implementación del puerto .NET de Apache PDFBox:
// Apache PDFBox .NET ports are experimental and incomplete
using PdfBoxDotNet.Pdmodel;
using PdfBoxDotNet.Text;
using System;
using System.IO;
class Program
{
static void Main()
{
// Note: PDFBox-dotnet has limited functionality
using (var document = PDDocument.Load("document.pdf"))
{
var stripper = new PDFTextStripper();
string text = stripper.GetText(document);
Console.WriteLine(text);
}
}
}
// Apache PDFBox .NET ports are experimental and incomplete
using PdfBoxDotNet.Pdmodel;
using PdfBoxDotNet.Text;
using System;
using System.IO;
class Program
{
static void Main()
{
// Note: PDFBox-dotnet has limited functionality
using (var document = PDDocument.Load("document.pdf"))
{
var stripper = new PDFTextStripper();
string text = stripper.GetText(document);
Console.WriteLine(text);
}
}
}
Imports PdfBoxDotNet.Pdmodel
Imports PdfBoxDotNet.Text
Imports System
Imports System.IO
Class Program
Shared Sub Main()
' Note: PDFBox-dotnet has limited functionality
Using document = PDDocument.Load("document.pdf")
Dim stripper = New PDFTextStripper()
Dim text As String = stripper.GetText(document)
Console.WriteLine(text)
End Using
End Sub
End Class
Implementación de 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);
}
}
// 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);
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim pdf = PdfDocument.FromFile("document.pdf")
Dim text As String = pdf.ExtractAllText()
Console.WriteLine(text)
' Or extract text from specific pages
Dim pageText As String = pdf.ExtractTextFromPage(0)
Console.WriteLine(pageText)
End Sub
End Class
IronPDF elimina por completo la clase PDFTextStripper y reemplaza la extracción de múltiples pasos con una única llamada de método.
Conversión de HTML a PDF
Apache PDFBox no admite la conversión de HTML a PDF de forma nativa, lo que representa una carencia de capacidad fundamental.
Implementación de 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");
}
}
// 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");
}
}
Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is HTML to PDF</p>")
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF created successfully")
End Sub
End Class
El motor de renderizado basado en Chromium deIronPDFofrece compatibilidad total con HTML, CSS y JavaScript. Para situaciones avanzadas, consulte la documentación HTML a PDF.
Fusión de varios PDF
Implementación del puerto .NET de Apache PDFBox:
// Apache PDFBox .NET port attempt (incomplete support)
using PdfBoxDotNet.Pdmodel;
using PdfBoxDotNet.Multipdf;
using System;
using System.IO;
class Program
{
static void Main()
{
// PDFBox-dotnet ports have incomplete API coverage
var merger = new PDFMergerUtility();
merger.AddSource("document1.pdf");
merger.AddSource("document2.pdf");
merger.SetDestinationFileName("merged.pdf");
merger.MergeDocuments();
Console.WriteLine("PDFs merged");
}
}
// Apache PDFBox .NET port attempt (incomplete support)
using PdfBoxDotNet.Pdmodel;
using PdfBoxDotNet.Multipdf;
using System;
using System.IO;
class Program
{
static void Main()
{
// PDFBox-dotnet ports have incomplete API coverage
var merger = new PDFMergerUtility();
merger.AddSource("document1.pdf");
merger.AddSource("document2.pdf");
merger.SetDestinationFileName("merged.pdf");
merger.MergeDocuments();
Console.WriteLine("PDFs merged");
}
}
Imports PdfBoxDotNet.Pdmodel
Imports PdfBoxDotNet.Multipdf
Imports System
Imports System.IO
Module Program
Sub Main()
' PDFBox-dotnet ports have incomplete API coverage
Dim merger As New PDFMergerUtility()
merger.AddSource("document1.pdf")
merger.AddSource("document2.pdf")
merger.SetDestinationFileName("merged.pdf")
merger.MergeDocuments()
Console.WriteLine("PDFs merged")
End Sub
End Module
Implementación de 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");
}
}
// 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");
}
}
Imports IronPdf
Imports System
Imports System.Collections.Generic
Module Program
Sub Main()
Dim pdf1 = PdfDocument.FromFile("document1.pdf")
Dim pdf2 = PdfDocument.FromFile("document2.pdf")
Dim pdf3 = PdfDocument.FromFile("document3.pdf")
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("merged.pdf")
Console.WriteLine("PDFs merged successfully")
End Sub
End Module
El método estático Merge deIronPDFacepta múltiples documentos directamente, eliminando el patrón de clase de utilidad.
Creación de PDF desde cero
La diferencia más dramática aparece a la hora de crear PDF. Apache PDFBox requiere un posicionamiento manual por coordenadas.
Implementación del puerto .NET de Apache PDFBox:
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();
}
}
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();
}
}
Imports org.apache.pdfbox.pdmodel
Imports org.apache.pdfbox.pdmodel.font
Imports org.apache.pdfbox.pdmodel.edit
Public Sub CreatePdf(outputPath As String)
Dim document As New PDDocument()
Try
Dim page As New PDPage()
document.addPage(page)
Dim contentStream As New PDPageContentStream(document, page)
Dim font As PDFont = 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()
End Try
End Sub
Implementación de 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);
}
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);
}
Imports IronPdf
Public Sub CreatePdf(outputPath As String)
Dim renderer As New ChromePdfRenderer()
Dim html As String = "
<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 pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
End Using
End Sub
La creación basada en HTML/CSS elimina los cálculos de coordenadas, la gestión de fuentes y la manipulación de flujos de contenido.
Añadir protección por contraseña
Implementación del puerto .NET de Apache PDFBox:
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();
}
}
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();
}
}
Imports org.apache.pdfbox.pdmodel
Imports org.apache.pdfbox.pdmodel.encryption
Public Sub ProtectPdf(inputPath As String, outputPath As String, password As String)
Dim document As PDDocument = PDDocument.load(New File(inputPath))
Try
Dim ap As New AccessPermission()
ap.setCanPrint(True)
ap.setCanExtractContent(False)
Dim spp As New StandardProtectionPolicy(password, password, ap)
spp.setEncryptionKeyLength(128)
document.protect(spp)
document.save(outputPath)
Finally
document.close()
End Try
End Sub
Implementación de 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);
}
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);
}
Imports IronPdf
Public Sub ProtectPdf(inputPath As String, outputPath As String, password As String)
Using pdf = PdfDocument.FromFile(inputPath)
pdf.SecuritySettings.UserPassword = password
pdf.SecuritySettings.OwnerPassword = password
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SaveAs(outputPath)
End Using
End Sub
IronPDF utiliza propiedades fuertemente tipadas en lugar de objetos separados de permisos y políticas.
Añadir marcas de agua
Implementación del puerto .NET de Apache PDFBox:
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();
}
}
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();
}
}
Imports org.apache.pdfbox.pdmodel
Imports org.apache.pdfbox.pdmodel.edit
Imports org.apache.pdfbox.pdmodel.font
Public Sub AddWatermark(inputPath As String, outputPath As String, watermarkText As String)
Dim document As PDDocument = PDDocument.load(New File(inputPath))
Try
Dim font As PDFont = PDType1Font.HELVETICA_BOLD
For i As Integer = 0 To document.getNumberOfPages() - 1
Dim page As PDPage = document.getPage(i)
Dim cs As 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()
Next
document.save(outputPath)
Finally
document.close()
End Try
End Sub
Implementación de 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);
}
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);
}
Imports IronPdf
Public Sub AddWatermark(inputPath As String, outputPath As String, watermarkText As String)
Using pdf = PdfDocument.FromFile(inputPath)
pdf.ApplyWatermark(
$"<h1 style='color:lightgray;font-size:72px;'>{watermarkText}</h1>",
rotation:=45,
opacity:=50)
pdf.SaveAs(outputPath)
End Using
End Sub
La marca de agua basada en HTML deIronPDFelimina la iteración de páginas y los cálculos de matrices.
Conversión de URL a PDF
Apache PDFBox no admite la conversión de URL a PDF.IronPDFproporciona soporte nativo:
using IronPdf;
public void ConvertUrlToPdf(string url, string outputPath)
{
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs(outputPath);
}
using IronPdf;
public void ConvertUrlToPdf(string url, string outputPath)
{
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs(outputPath);
}
Imports IronPdf
Public Sub ConvertUrlToPdf(url As String, outputPath As String)
Dim renderer As New ChromePdfRenderer()
Using pdf = renderer.RenderUrlAsPdf(url)
pdf.SaveAs(outputPath)
End Using
End Sub
Para conocer todas las opciones de conversión de URL, consulte la documentación de URL a PDF.
Cabeceras y pies de página
Apache PDFBox requiere posicionamiento manual en cada página sin soporte integrado de encabezado/pie de página.IronPDFofrece una configuración declarativa:
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);
}
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);
}
Imports IronPdf
Public Sub CreatePdfWithHeaderFooter(html As String, outputPath As String)
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader = New TextHeaderFooter With {
.CenterText = "Document Title",
.FontSize = 12
}
renderer.RenderingOptions.TextFooter = New TextHeaderFooter With {
.CenterText = "Page {page} of {total-pages}",
.FontSize = 10
}
Using pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs(outputPath)
End Using
End Sub
Para diseños avanzados, consulte la documentación sobre encabezados y pies de página.
Integración con .NET Core
IronPDF se integra de forma natural con las modernas aplicaciones web .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");
}
[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");
}
<HttpPost>
Public Function GeneratePdf(<FromBody> request As ReportRequest) As IActionResult
Dim renderer As New ChromePdfRenderer()
Using pdf = renderer.RenderHtmlAsPdf(request.Html)
Return File(pdf.BinaryData, "application/pdf", "report.pdf")
End Using
End Function
Soporte Async
Los puertos de Apache PDFBox no admiten operaciones asíncronas.IronPDFofrece todas las funciones 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;
}
using IronPdf;
public async Task<byte[]> GeneratePdfAsync(string html)
{
var renderer = new ChromePdfRenderer();
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return pdf.BinaryData;
}
Imports IronPdf
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
Dim renderer As New ChromePdfRenderer()
Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Using
End Function
Configuración de la inyección de dependencias
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();
}
}
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();
}
}
Imports System.Threading.Tasks
Public Interface IPdfService
Function GeneratePdfAsync(html As String) As Task(Of Byte())
Function ExtractText(pdfPath As String) As String
End Interface
Public Class IronPdfService
Implements IPdfService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer()
_renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
End Sub
Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte()) Implements IPdfService.GeneratePdfAsync
Using pdf = Await _renderer.RenderHtmlAsPdfAsync(html)
Return pdf.BinaryData
End Using
End Function
Public Function ExtractText(pdfPath As String) As String Implements IPdfService.ExtractText
Using pdf = PdfDocument.FromFile(pdfPath)
Return pdf.ExtractAllText()
End Using
End Function
End Class
Optimización del rendimiento
Comparación del uso de memoria
| Escenario | Puerto .NET de Apache PDFBox | IronPDF |
|---|---|---|
| Extracción de texto | ~80 MB | ~50 MB |
| Creación de PDF | ~100 MB | ~60 MB |
| Lote (100 PDF) | Alto (limpieza manual) | ~100 MB |
Consejos de optimización
Utilice las declaraciones using:
// Automáticocleanup with IDisposable pattern
using var pdf = PdfDocument.FromFile(path);
// Automáticocleanup with IDisposable pattern
using var pdf = PdfDocument.FromFile(path);
Renderizador de reutilización para operaciones por lotes:
var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs($"output_{i}.pdf");
}
var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs($"output_{i}.pdf");
}
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
For Each html In htmlList
Using pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs($"output_{i}.pdf")
End Using
Next
Uso de Async en aplicaciones web:
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
Solución de problemas comunes de migración
Asunto: Nombres de métodos estilo Java no encontrados
Reemplace los métodos Java camelCase con equivalentes .NET PascalCase:
// PDFBox: stripper.getText(document)
// IronPDF: pdf.ExtractAllText()
// PDFBox: document.getNumberOfPages()
// IronPDF: pdf.PageCount
// PDFBox: stripper.getText(document)
// IronPDF: pdf.ExtractAllText()
// PDFBox: document.getNumberOfPages()
// IronPDF: pdf.PageCount
' PDFBox: stripper.getText(document)
' IronPDF: pdf.ExtractAllText()
' PDFBox: document.getNumberOfPages()
' IronPDF: pdf.PageCount
Problema: No hay método close()
IronPDF utiliza el patrón IDisposable:
// PDFBox
document.close();
// IronPDF
using var pdf = PdfDocument.FromFile(path);
// Automáticodisposal at end of scope
// PDFBox
document.close();
// IronPDF
using var pdf = PdfDocument.FromFile(path);
// Automáticodisposal at end of scope
Problema: No hay equivalente a PDFTextStripper
La extracción de texto se simplifica a un único método:
// IronPDF: Just call ExtractAllText()
string text = pdf.ExtractAllText();
// Per-page extraction:
string pageText = pdf.Pages[0].Text;
// IronPDF: Just call ExtractAllText()
string text = pdf.ExtractAllText();
// Per-page extraction:
string pageText = pdf.Pages[0].Text;
' IronPDF: Just call ExtractAllText()
Dim text As String = pdf.ExtractAllText()
' Per-page extraction:
Dim pageText As String = pdf.Pages(0).Text
Problema: PDFMergerUtility No encontrado
Utilice el método estático Merge:
//IronPDFuses static Merge
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
//IronPDFuses static Merge
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
' IronPDF uses static Merge
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
Lista de comprobación posterior a la migración
Después de completar la migración del código, verifique lo siguiente:
- Ejecutar todas las pruebas unitarias y de integración existentes
- Comparar visualmente las salidas PDF con versiones anteriores
- Prueba la precisión de la extracción de texto
- Verificar que el licenciamiento funcione correctamente (
IronPdf.License.IsLicensed) - Comparación del rendimiento con la implementación anterior
- Actualizar las dependencias de la canalización de CI/CD
- Documente nuevos patrones para su equipo de desarrollo
Proteja su infraestructura PDF
Con .NET 10 en el horizonte y C# 14 introduciendo nuevas características del lenguaje, elegir una biblioteca PDF nativa de .NET garantiza la compatibilidad con las capacidades de tiempo de ejecución en evolución. El compromiso deIronPDFde dar soporte a las últimas versiones de .NET significa que su inversión en migración dará sus frutos a medida que los proyectos se extiendan hasta 2025 y 2026.
Recursos adicionales
La migración de los puertos .NET de Apache PDFBox aIronPDFtransforma su código PDF de patrones de estilo Java a C# idiomático. El cambio del posicionamiento manual por coordenadas al renderizado HTML/CSS, combinado con la compatibilidad nativa con async y la integración moderna con .NET, proporciona un código más limpio y fácil de mantener con un soporte profesional que respalda sus aplicaciones de producción.

