Passer au contenu du pied de page
VIDéOS

Comment dessiner des lignes et des rectangles sur des PDFs

Le SDK Adobe PDF Library (APDFL) est distribué par Datalogics sous licence d'Adobe et partage le code source principal avec le moteur Acrobat. Il est puissant, mais son modèle de tarification dirigé par les ventes, son empreinte d'exécution native, le manque d'un moteur de rendu HTML intégré et le design de l'API à bas niveau poussent de nombreuses équipes .NET à envisager des alternatives. Ce guide offre un chemin de migration étape par étape du SDK Adobe PDF Library vers IronPDF— une bibliothèque PDF .NET moderne supportant de .NET Framework 4.6.2 à .NET 9.

Pourquoi envisager de passer à une autre solution que le kit de développement logiciel (SDK) Adobe PDF Library ?

Bien que l'APDFL offre le moteur PDF dérivé d'Acrobat, plusieurs facteurs incitent les équipes de développement à explorer des alternatives pour HTML en PDF, la manipulation de documents et la génération de rapports.

Tarification Personnalisée, Dirigée par les Ventes

Datalogics ne publie pas de prix indicatifs pour l'APDFL. Selon les pages de tarification de Datalogics, les plans d'utilisation interne commencent à environ 5 999 $/an, et les déploiements OEM, ISV et SaaS négocient des frais par plateforme en plus des redevances ou du partage des revenus. Le coût total est généralement hors de portée pour les équipes de taille petite à moyenne et nécessite presque toujours une conversation commerciale.

Intégration complexe du SDK natif

L'APDFL encapsule un moteur natif C/C++ qui partage sa lignée avec Acrobat. La liaison .NET (Datalogics.PDFL) nécessite des binaires d'exécution spécifiques à la plateforme — le package NuGet Adobe.PDF.Library.LM.NET livre des charges utiles ARM x64 pour Windows, Linux, et macOS — une gestion attentive de la mémoire, et un cycle de vie explicite Library pour chaque point d'entrée. Cela ajoute de la charge de développement et complique les pipelines CI/CD.

Pas de Rendeur HTML Intégré

La liste de conversion documentée de l'APDFL couvre PDF/A, PDF/X, ZUGFeRD, EPS, PS, XPS, et les formats Office, mais pas HTML. Produire un PDF à partir d'une chaîne HTML avec l'APDFL seul signifie construire manuellement des pages, des polices, et des exécutions de contenu, ou coupler l'APDFL avec un moteur de rendu HTML distinct.

Conception d'API de bas niveau

Créer des PDF avec l'APDFL implique de construire programmétiquement des pages, des flux de contenu, des séries de texte et des polices. Des tâches simples comme le rendu d'une chaîne HTML deviennent des opérations multi-étapes nécessitant des calculs de coordonnées, l'intégration des polices, et la gestion manuelle des éléments de contenu.

Gestion du cycle de vie des bibliothèques : frais généraux

Chaque point d'entrée nécessite d'encadrer le code dans using (var lib = new Library()) (ou des appels appariés Library.Initialize() / Library.Terminate()) avec une élimination attentive de chaque objet PDF créé à l'intérieur. Un nettoyage manqué peut produire des fuites de ressources.

Trop Encombrant pour De Nombreux Projets

Pour les applications ayant principalement besoin de conversion HTML en PDF, de manipulation de document de base ou de génération de rapports, le moteur complet dérivé d'Acrobat est souvent plus que la charge de travail ne nécessite.

Bibliothèque Adobe PDF SDKvs.IronPDF: Principales différences

La compréhension des différences architecturales fondamentales entre ces bibliothèques permet de planifier une stratégie de migration efficace.

Aspect Bibliothèque Adobe PDF SDK IronPDF
Tarification Dirigé par les ventes; Usage interne à partir de ~5 999 $/an, redevances OEM/SaaS en supplément Transparent par développeur / par déploiement
Installation Adobe.PDF.Library.LM.NET envoie des runtimes natifs par plateforme Simple Paquet NuGet
Création de documents Construction de pages/contenus de bas niveau Rendu HTML/CSS
HTML à PDF Non intégré ChromePdfRenderer.RenderHtmlAsPdf
Initialisation using (Library lib = new Library()) requis Automatique
Système de coordonnées Points PostScript, origine en bas à gauche Mise en page basée sur les CSS
Traitement des polices Intégration manuelle requise Automatique
Gestion de la mémoire Élimination manuelle de chaque objet PDF Modèle standard IDisposable
Support asynchrone Non disponible Prise en charge complète de l'asynchronisme et de l'attente

Préparation de la migration

Prérequis

Assurez-vous que votre environnement répond à ces exigences avant de commencer la migration :

  • .NET Framework 4.6.2+ ou .NET Core 3.1 / .NET 5-9
  • Visual Studio 2019+ ou JetBrains Rider
  • Accès au Package Manager NuGet
  • Clé de licence IronPDF(essai gratuit disponible sur ironpdf.com)

Audit de l'utilisation de la bibliothèque Adobe PDF SDK

Exécutez ces commandes dans votre répertoire de solutions pour identifier toutes les références à Bibliothèque Adobe PDF SDK:

grep -r "using Datalogics" --include="*.cs" .
grep -r "Adobe.PDF.Library" --include="*.csproj" .
grep -r "Library.Initialize\|Library.Terminate" --include="*.cs" .
grep -r "using Datalogics" --include="*.cs" .
grep -r "Adobe.PDF.Library" --include="*.csproj" .
grep -r "Library.Initialize\|Library.Terminate" --include="*.cs" .
SHELL

Modifications importantes à prévoir

Catégorie Bibliothèque Adobe PDF SDK IronPDF Action de migration
Initialisation Library.Initialize() / Terminate() Automatique Supprimer le code du cycle de vie
Création de documents new Document() avec construction de page ChromePdfRenderer Utiliser le rendu HTML
Système de coordonnées Points PostScript, origine en bas à gauche Mise en page basée sur les CSS Utiliser HTML/CSS
Traitement des polices Création et intégration manuelles Font Automatique Supprimer le code de police
Gestion de la mémoire Élimination manuelle des objets COM IDisposable standard Utilisez des déclarations using
Construction de la page CreatePage(), AddContent() Automatique à partir de HTML Simplifier considérablement

Processus de migration étape par étape

Étape 1 : Mise à jour des paquets NuGet

Supprimez le kit SDK de la bibliothèque Adobe PDF et installez IronPDF:

# Remove Adobe PDF Library (.NET 6/7/8 projects)
dotnet remove package Adobe.PDF.Library.LM.NET
# .NET Framework projects use the LM.NETFramework variant
dotnet remove package Adobe.PDF.Library.LM.NETFramework

# Install IronPDF
dotnet add package IronPdf
# Remove Adobe PDF Library (.NET 6/7/8 projects)
dotnet remove package Adobe.PDF.Library.LM.NET
# .NET Framework projects use the LM.NETFramework variant
dotnet remove package Adobe.PDF.Library.LM.NETFramework

# Install IronPDF
dotnet add package IronPdf
SHELL

Étape 2 : configuration de la clé de licence

Remplacez la licence Adobe par la clé de licence IronPDF basée sur le code :

// Replace Adobe's Library.LicenseKey with IronPDF license
// Add at application startup, before any IronPDF operations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

// Verify license status
bool isLicensed = IronPdf.License.IsLicensed;
// Replace Adobe's Library.LicenseKey with IronPDF license
// Add at application startup, before any IronPDF operations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

// Verify license status
bool isLicensed = IronPdf.License.IsLicensed;
' Replace Adobe's Library.LicenseKey with IronPDF license
' Add at application startup, before any IronPDF operations
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"

' Verify license status
Dim isLicensed As Boolean = IronPdf.License.IsLicensed
$vbLabelText   $csharpLabel

Étape 3 : mise à jour des références aux espaces de noms

Effectuez une recherche et un remplacement globaux dans votre solution :

Recherche Remplacer par
using Datalogics.PDFL; using IronPdf;

APDFL expose un seul espace de noms racine, Datalogics.PDFL. Document, Page, Content, Font, et Color sont toutes des classes à l'intérieur de cet espace de noms, donc il y a juste une directive using à échanger.

Etape 4 : Supprimer le code du cycle de vie de la bibliothèque

L'une des simplifications les plus importantes consiste à supprimer les modèles d'initialisation et de terminaison :

// Bibliothèque Adobe PDF SDK- REMOVE THIS PATTERN
Library.Initialize();
try
{
    // PDF operations
}
finally
{
    Library.Terminate(); // Must always terminate
}

//IronPDF- Just use directly
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Bibliothèque Adobe PDF SDK- REMOVE THIS PATTERN
Library.Initialize();
try
{
    // PDF operations
}
finally
{
    Library.Terminate(); // Must always terminate
}

//IronPDF- Just use directly
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Imports IronPdf

' Bibliothèque Adobe PDF SDK- REMOVE THIS PATTERN
Library.Initialize()
Try
    ' PDF operations
Finally
    Library.Terminate() ' Must always terminate
End Try

' IronPDF- Just use directly
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
$vbLabelText   $csharpLabel

Référence complète de migration des API

Méthodes de cycle de vie des bibliothèques

Méthode Adobe Équivalent d'IronPDF
Library.Initialize() Pas nécessaire
Library.Terminate() Pas nécessaire
Library.LicenseKey = "KEY" IronPdf.License.LicenseKey = "KEY"
using (Library lib = new Library()) Pas nécessaire

Méthodes de création de documents

Méthode Adobe Méthode IronPDF
new Document() new ChromePdfRenderer()
new Document(path) PdfDocument.FromFile(path)
doc.CreatePage(index, rect) Automatique à partir de HTML
doc.Save(SaveFlags.Full, path) pdf.SaveAs(path)
doc.NumPages pdf.PageCount
doc.GetPage(index) pdf.Pages[index]
doc.InsertPages(insertAfter, src, start, count, flags) PdfDocument.Merge(pdfs)

Création de contenu (changement de paradigme majeur)

Adobe PDF Library SDK nécessite une construction de contenu de bas niveau.IronPDF utilise HTML/CSS :

Méthode Adobe Méthode IronPDF
new Text() Utilisez HTML <p>, <h1>, etc.
text.AddRun(textRun) Utiliser HTML
new TextRun(text, font, size, point) Style CSS
new Font(name, flags) CSS font-family
new Image(path) Balise HTML <img>
content.AddElement(...) Contenu HTML
page.UpdateContent() Pas nécessaire

Filigrane et méthodes de sécurité

Méthode Adobe Méthode IronPDF
doc.Watermark(textParams, wmParams) pdf.ApplyWatermark(html)
WatermarkParams.Opacity (0.0-1.0) Paramètre opacity (0-100) ou CSS opacity
new EncryptionHandler(user, owner, perms) pdf.SecuritySettings
PermissionFlags.PrintDoc AllowUserPrinting

Extraction de texte

Méthode Adobe Méthode IronPDF
new WordFinder(doc, config) pdf.ExtractAllText()
wordFinder.GetWordList() pdf.Pages[i].Text
Itération de mots/caractères complexes Appel de méthode unique

Exemples de migration de code

Conversion HTML en PDF

L'APDFL ne dispose pas d'un meneur HTML intégré. Le plus proche équivalent consiste à construire des pages et des exécutions de contenu à la main pour imiter le layout qu'un document HTML produirait - ou à coupler l'APDFL avec un moteur HTML-to-PDF distinct.

Mise en œuvre de la bibliothèque SDK d'Adobe PDF:

// Bibliothèque Adobe PDF SDK(Datalogics APDFL)
// NuGet: Adobe.PDF.Library.LM.NET — namespace Datalogics.PDFL
using Datalogics.PDFL;
using System;

class AdobeHtmlToPdf
{
    static void Main()
    {
        using (Library lib = new Library())
        using (Document doc = new Document())
        {
            // US Letter in points (8.5 x 11 inches @ 72 DPI)
            Rect pageRect = new Rect(0, 0, 612, 792);
            using (Page page = doc.CreatePage(Document.BeforeFirstPage, pageRect))
            {
                Content content = page.Content;
                Font font = new Font("Helvetica", FontCreateFlags.Embedded);

                Text text = new Text();
                text.AddRun(new TextRun("Hello World", font, 24, new Point(72, 720)));
                content.AddElement(text);

                page.UpdateContent();
            }

            doc.Save(SaveFlags.Full, "output.pdf");
        }
    }
}
// Bibliothèque Adobe PDF SDK(Datalogics APDFL)
// NuGet: Adobe.PDF.Library.LM.NET — namespace Datalogics.PDFL
using Datalogics.PDFL;
using System;

class AdobeHtmlToPdf
{
    static void Main()
    {
        using (Library lib = new Library())
        using (Document doc = new Document())
        {
            // US Letter in points (8.5 x 11 inches @ 72 DPI)
            Rect pageRect = new Rect(0, 0, 612, 792);
            using (Page page = doc.CreatePage(Document.BeforeFirstPage, pageRect))
            {
                Content content = page.Content;
                Font font = new Font("Helvetica", FontCreateFlags.Embedded);

                Text text = new Text();
                text.AddRun(new TextRun("Hello World", font, 24, new Point(72, 720)));
                content.AddElement(text);

                page.UpdateContent();
            }

            doc.Save(SaveFlags.Full, "output.pdf");
        }
    }
}
Imports Datalogics.PDFL
Imports System

Class AdobeHtmlToPdf
    Shared Sub Main()
        Using lib As New Library()
            Using doc As New Document()
                ' US Letter in points (8.5 x 11 inches @ 72 DPI)
                Dim pageRect As New Rect(0, 0, 612, 792)
                Using page As Page = doc.CreatePage(Document.BeforeFirstPage, pageRect)
                    Dim content As Content = page.Content
                    Dim font As New Font("Helvetica", FontCreateFlags.Embedded)

                    Dim text As New Text()
                    text.AddRun(New TextRun("Hello World", font, 24, New Point(72, 720)))
                    content.AddElement(text)

                    page.UpdateContent()
                End Using

                doc.Save(SaveFlags.Full, "output.pdf")
            End Using
        End Using
    End Sub
End Class
$vbLabelText   $csharpLabel

Mise en œuvre d'IronPDF:

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

class IronPdfHtmlToPdf
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        string htmlContent = "<html><body><h1>Hello World</h1></body></html>";

        // Convert HTML to PDF with simple API
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class IronPdfHtmlToPdf
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        string htmlContent = "<html><body><h1>Hello World</h1></body></html>";

        // Convert HTML to PDF with simple API
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs("output.pdf");
    }
}
Imports IronPdf
Imports System

Class IronPdfHtmlToPdf
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim htmlContent As String = "<html><body><h1>Hello World</h1></body></html>"

        ' Convert HTML to PDF with simple API
        Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF élimine l'enveloppe du cycle de vie de la bibliothèque, les objets de paramètres de conversion et l'élimination explicite. Le ChromePdfRenderer utilise un moteur basé sur Chromium pour un support CSS et JavaScript au pixel près. Pour les scénarios avancés, consultez la documentation HTML vers PDF.

Fusionner plusieurs fichiers PDF

La fusion des PDF montre clairement la différence de complexité des API.

Mise en œuvre de la bibliothèque SDK d'Adobe PDF:

// Bibliothèque Adobe PDF SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;

class AdobeMergePdfs
{
    static void Main()
    {
        using (Library lib = new Library())
        using (Document doc1 = new Document("document1.pdf"))
        using (Document doc2 = new Document("document2.pdf"))
        {
            // InsertPages(insertAfter, sourceDoc, sourceStartPage, pageCount, flags)
            doc1.InsertPages(
                Document.LastPage,
                doc2,
                0,
                Document.AllPages,
                PageInsertFlags.Bookmarks | PageInsertFlags.Threads);

            doc1.Save(SaveFlags.Full, "merged.pdf");
        }
    }
}
// Bibliothèque Adobe PDF SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;

class AdobeMergePdfs
{
    static void Main()
    {
        using (Library lib = new Library())
        using (Document doc1 = new Document("document1.pdf"))
        using (Document doc2 = new Document("document2.pdf"))
        {
            // InsertPages(insertAfter, sourceDoc, sourceStartPage, pageCount, flags)
            doc1.InsertPages(
                Document.LastPage,
                doc2,
                0,
                Document.AllPages,
                PageInsertFlags.Bookmarks | PageInsertFlags.Threads);

            doc1.Save(SaveFlags.Full, "merged.pdf");
        }
    }
}
Imports Datalogics.PDFL
Imports System

Class AdobeMergePdfs
    Shared Sub Main()
        Using lib As New Library()
            Using doc1 As New Document("document1.pdf")
                Using doc2 As New Document("document2.pdf")
                    ' InsertPages(insertAfter, sourceDoc, sourceStartPage, pageCount, flags)
                    doc1.InsertPages(Document.LastPage, doc2, 0, Document.AllPages, PageInsertFlags.Bookmarks Or PageInsertFlags.Threads)

                    doc1.Save(SaveFlags.Full, "merged.pdf")
                End Using
            End Using
        End Using
    End Sub
End Class
$vbLabelText   $csharpLabel

Mise en œuvre d'IronPDF:

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

class IronPdfMergePdfs
{
    static void Main()
    {
        // Load PDF documents
        var pdf1 = PdfDocument.FromFile("document1.pdf");
        var pdf2 = PdfDocument.FromFile("document2.pdf");

        // Merge PDFs with simple method
        var merged = PdfDocument.Merge(pdf1, pdf2);
        merged.SaveAs("merged.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class IronPdfMergePdfs
{
    static void Main()
    {
        // Load PDF documents
        var pdf1 = PdfDocument.FromFile("document1.pdf");
        var pdf2 = PdfDocument.FromFile("document2.pdf");

        // Merge PDFs with simple method
        var merged = PdfDocument.Merge(pdf1, pdf2);
        merged.SaveAs("merged.pdf");
    }
}
Imports IronPdf
Imports System

Class IronPdfMergePdfs
    Shared Sub Main()
        ' Load PDF documents
        Dim pdf1 = PdfDocument.FromFile("document1.pdf")
        Dim pdf2 = PdfDocument.FromFile("document2.pdf")

        ' Merge PDFs with simple method
        Dim merged = PdfDocument.Merge(pdf1, pdf2)
        merged.SaveAs("merged.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

L'approche d'Adobe nécessite une itération page par page avec des paramètres d'insertion.IronPDF fournit une méthode Merge unique qui accepte plusieurs documents.

Ajouter des filigranes

Le filigrane illustre la façon dont IronPDF tire parti de HTML/CSS pour la flexibilité du style.

Mise en œuvre de la bibliothèque SDK d'Adobe PDF:

// Bibliothèque Adobe PDF SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;

class AdobeAddWatermark
{
    static void Main()
    {
        using (Library lib = new Library())
        using (Document doc = new Document("input.pdf"))
        {
            WatermarkParams watermarkParams = new WatermarkParams();
            watermarkParams.Opacity = 0.5; // 0.0 - 1.0
            watermarkParams.Rotation = 45.0;
            watermarkParams.Scale = -1; // auto-fit

            WatermarkTextParams textParams = new WatermarkTextParams();
            textParams.Text = "CONFIDENTIAL";
            textParams.Color = new Color(0.8, 0.8, 0.8);
            textParams.TextAlign = HorizontalAlignment.Center;

            // Apply via Document.Watermark(textParams, wmParams)
            doc.Watermark(textParams, watermarkParams);

            doc.Save(SaveFlags.Full, "watermarked.pdf");
        }
    }
}
// Bibliothèque Adobe PDF SDK(Datalogics APDFL)
using Datalogics.PDFL;
using System;

class AdobeAddWatermark
{
    static void Main()
    {
        using (Library lib = new Library())
        using (Document doc = new Document("input.pdf"))
        {
            WatermarkParams watermarkParams = new WatermarkParams();
            watermarkParams.Opacity = 0.5; // 0.0 - 1.0
            watermarkParams.Rotation = 45.0;
            watermarkParams.Scale = -1; // auto-fit

            WatermarkTextParams textParams = new WatermarkTextParams();
            textParams.Text = "CONFIDENTIAL";
            textParams.Color = new Color(0.8, 0.8, 0.8);
            textParams.TextAlign = HorizontalAlignment.Center;

            // Apply via Document.Watermark(textParams, wmParams)
            doc.Watermark(textParams, watermarkParams);

            doc.Save(SaveFlags.Full, "watermarked.pdf");
        }
    }
}
Imports Datalogics.PDFL
Imports System

Class AdobeAddWatermark
    Shared Sub Main()
        Using lib As New Library()
            Using doc As New Document("input.pdf")
                Dim watermarkParams As New WatermarkParams()
                watermarkParams.Opacity = 0.5 ' 0.0 - 1.0
                watermarkParams.Rotation = 45.0
                watermarkParams.Scale = -1 ' auto-fit

                Dim textParams As New WatermarkTextParams()
                textParams.Text = "CONFIDENTIAL"
                textParams.Color = New Color(0.8, 0.8, 0.8)
                textParams.TextAlign = HorizontalAlignment.Center

                ' Apply via Document.Watermark(textParams, wmParams)
                doc.Watermark(textParams, watermarkParams)

                doc.Save(SaveFlags.Full, "watermarked.pdf")
            End Using
        End Using
    End Sub
End Class
$vbLabelText   $csharpLabel

Mise en œuvre d'IronPDF:

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

class IronPdfAddWatermark
{
    static void Main()
    {
        var pdf = PdfDocument.FromFile("input.pdf");

        // Apply text watermark with simple API
        pdf.ApplyWatermark("<h1 style='color:red; opacity:0.5;'>CONFIDENTIAL</h1>",
            rotation: 45,
            verticalAlignment: VerticalAlignment.Middle,
            horizontalAlignment: HorizontalAlignment.Center);

        pdf.SaveAs("watermarked.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Editing;
using System;

class IronPdfAddWatermark
{
    static void Main()
    {
        var pdf = PdfDocument.FromFile("input.pdf");

        // Apply text watermark with simple API
        pdf.ApplyWatermark("<h1 style='color:red; opacity:0.5;'>CONFIDENTIAL</h1>",
            rotation: 45,
            verticalAlignment: VerticalAlignment.Middle,
            horizontalAlignment: HorizontalAlignment.Center);

        pdf.SaveAs("watermarked.pdf");
    }
}
Imports IronPdf
Imports IronPdf.Editing
Imports System

Class IronPdfAddWatermark
    Shared Sub Main()
        Dim pdf = PdfDocument.FromFile("input.pdf")

        ' Apply text watermark with simple API
        pdf.ApplyWatermark("<h1 style='color:red; opacity:0.5;'>CONFIDENTIAL</h1>",
                           rotation:=45,
                           verticalAlignment:=VerticalAlignment.Middle,
                           horizontalAlignment:=HorizontalAlignment.Center)

        pdf.SaveAs("watermarked.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

Le filigrane basé sur HTML d'IronPDF permet un contrôle complet de la conception grâce au style CSS, ce qui élimine le besoin d'objets de paramètres distincts.

Protection et chiffrement des mots de passe

Mise en œuvre de la bibliothèque SDK d'Adobe PDF:

using Datalogics.PDFL;

public void ProtectPdf(string inputPath, string outputPath, string password)
{
    Library.Initialize();
    try
    {
        using (Document doc = new Document(inputPath))
        {
            PermissionFlags permissions =
                PermissionFlags.PrintDoc |
                PermissionFlags.PrintFidelity;

            EncryptionHandler encHandler = new EncryptionHandler(
                password,      // User password
                password,      // Owner password
                permissions,
                EncryptionMethod.AES256);

            doc.SetEncryptionHandler(encHandler);
            doc.Save(SaveFlags.Full | SaveFlags.Encrypted, outputPath);
        }
    }
    finally
    {
        Library.Terminate();
    }
}
using Datalogics.PDFL;

public void ProtectPdf(string inputPath, string outputPath, string password)
{
    Library.Initialize();
    try
    {
        using (Document doc = new Document(inputPath))
        {
            PermissionFlags permissions =
                PermissionFlags.PrintDoc |
                PermissionFlags.PrintFidelity;

            EncryptionHandler encHandler = new EncryptionHandler(
                password,      // User password
                password,      // Owner password
                permissions,
                EncryptionMethod.AES256);

            doc.SetEncryptionHandler(encHandler);
            doc.Save(SaveFlags.Full | SaveFlags.Encrypted, outputPath);
        }
    }
    finally
    {
        Library.Terminate();
    }
}
Imports Datalogics.PDFL

Public Sub ProtectPdf(inputPath As String, outputPath As String, password As String)
    Library.Initialize()
    Try
        Using doc As New Document(inputPath)
            Dim permissions As PermissionFlags = PermissionFlags.PrintDoc Or PermissionFlags.PrintFidelity

            Dim encHandler As New EncryptionHandler(
                password,      ' User password
                password,      ' Owner password
                permissions,
                EncryptionMethod.AES256)

            doc.SetEncryptionHandler(encHandler)
            doc.Save(SaveFlags.Full Or SaveFlags.Encrypted, outputPath)
        End Using
    Finally
        Library.Terminate()
    End Try
End Sub
$vbLabelText   $csharpLabel

Mise en œuvre d'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.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

    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.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

    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.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit

        pdf.SaveAs(outputPath)
    End Using
End Sub
$vbLabelText   $csharpLabel

IronPDF utilise des propriétés fortement typées au lieu de drapeaux de permission en bits et d'objets de gestion du chiffrement.

Extraction de texte

Mise en œuvre de la bibliothèque SDK d'Adobe PDF:

using Datalogics.PDFL;

public string ExtractText(string pdfPath)
{
    string extractedText = "";

    Library.Initialize();
    try
    {
        using (Document doc = new Document(pdfPath))
        {
            WordFinderConfig config = new WordFinderConfig();
            config.IgnoreCharGaps = true;

            for (int i = 0; i < doc.NumPages; i++)
            {
                using (WordFinder wordFinder = new WordFinder(doc, i, config))
                {
                    IList<Word> words = wordFinder.GetWordList();
                    foreach (Word word in words)
                    {
                        extractedText += word.Text + " ";
                    }
                    extractedText += "\n";
                }
            }
        }
    }
    finally
    {
        Library.Terminate();
    }

    return extractedText;
}
using Datalogics.PDFL;

public string ExtractText(string pdfPath)
{
    string extractedText = "";

    Library.Initialize();
    try
    {
        using (Document doc = new Document(pdfPath))
        {
            WordFinderConfig config = new WordFinderConfig();
            config.IgnoreCharGaps = true;

            for (int i = 0; i < doc.NumPages; i++)
            {
                using (WordFinder wordFinder = new WordFinder(doc, i, config))
                {
                    IList<Word> words = wordFinder.GetWordList();
                    foreach (Word word in words)
                    {
                        extractedText += word.Text + " ";
                    }
                    extractedText += "\n";
                }
            }
        }
    }
    finally
    {
        Library.Terminate();
    }

    return extractedText;
}
Imports Datalogics.PDFL

Public Function ExtractText(ByVal pdfPath As String) As String
    Dim extractedText As String = ""

    Library.Initialize()
    Try
        Using doc As New Document(pdfPath)
            Dim config As New WordFinderConfig()
            config.IgnoreCharGaps = True

            For i As Integer = 0 To doc.NumPages - 1
                Using wordFinder As New WordFinder(doc, i, config)
                    Dim words As IList(Of Word) = wordFinder.GetWordList()
                    For Each word As Word In words
                        extractedText &= word.Text & " "
                    Next
                    extractedText &= vbLf
                End Using
            Next
        End Using
    Finally
        Library.Terminate()
    End Try

    Return extractedText
End Function
$vbLabelText   $csharpLabel

Mise en œuvre d'IronPDF:

using IronPdf;

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

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

Public Function ExtractText(pdfPath As String) As String
    Using pdf = PdfDocument.FromFile(pdfPath)
        Return pdf.ExtractAllText()
    End Using
End Function
$vbLabelText   $csharpLabel

L'itération mot à mot d'Adobe se transforme en un simple appel de méthode avec IronPDF.

En-têtes et pieds de page

Mise en œuvre de la bibliothèque SDK d'Adobe PDF:

using Datalogics.PDFL;

public void AddHeaderFooter(string inputPath, string outputPath)
{
    Library.Initialize();
    try
    {
        using (Document doc = new Document(inputPath))
        {
            Font font = new Font("Helvetica", FontCreateFlags.None);

            for (int i = 0; i < doc.NumPages; i++)
            {
                using (Page page = doc.GetPage(i))
                {
                    Content content = page.Content;

                    // Add header
                    Text header = new Text();
                    header.AddRun(new TextRun("Document Header",
                        font, 10, new Point(72, page.MediaBox.Top - 36)));
                    content.AddElement(header);

                    // Add footer with page number
                    Text footer = new Text();
                    footer.AddRun(new TextRun($"Page {i + 1} of {doc.NumPages}",
                        font, 10, new Point(72, 36)));
                    content.AddElement(footer);

                    page.UpdateContent();
                }
            }
            doc.Save(SaveFlags.Full, outputPath);
        }
    }
    finally
    {
        Library.Terminate();
    }
}
using Datalogics.PDFL;

public void AddHeaderFooter(string inputPath, string outputPath)
{
    Library.Initialize();
    try
    {
        using (Document doc = new Document(inputPath))
        {
            Font font = new Font("Helvetica", FontCreateFlags.None);

            for (int i = 0; i < doc.NumPages; i++)
            {
                using (Page page = doc.GetPage(i))
                {
                    Content content = page.Content;

                    // Add header
                    Text header = new Text();
                    header.AddRun(new TextRun("Document Header",
                        font, 10, new Point(72, page.MediaBox.Top - 36)));
                    content.AddElement(header);

                    // Add footer with page number
                    Text footer = new Text();
                    footer.AddRun(new TextRun($"Page {i + 1} of {doc.NumPages}",
                        font, 10, new Point(72, 36)));
                    content.AddElement(footer);

                    page.UpdateContent();
                }
            }
            doc.Save(SaveFlags.Full, outputPath);
        }
    }
    finally
    {
        Library.Terminate();
    }
}
Imports Datalogics.PDFL

Public Sub AddHeaderFooter(inputPath As String, outputPath As String)
    Library.Initialize()
    Try
        Using doc As New Document(inputPath)
            Dim font As New Font("Helvetica", FontCreateFlags.None)

            For i As Integer = 0 To doc.NumPages - 1
                Using page As Page = doc.GetPage(i)
                    Dim content As Content = page.Content

                    ' Add header
                    Dim header As New Text()
                    header.AddRun(New TextRun("Document Header", font, 10, New Point(72, page.MediaBox.Top - 36)))
                    content.AddElement(header)

                    ' Add footer with page number
                    Dim footer As New Text()
                    footer.AddRun(New TextRun($"Page {i + 1} of {doc.NumPages}", font, 10, New Point(72, 36)))
                    content.AddElement(footer)

                    page.UpdateContent()
                End Using
            Next
            doc.Save(SaveFlags.Full, outputPath)
        End Using
    Finally
        Library.Terminate()
    End Try
End Sub
$vbLabelText   $csharpLabel

Mise en œuvre d'IronPDF:

using IronPdf;

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

    renderer.RenderingOptions.TextHeader = new TextHeaderFooter
    {
        CenterText = "Document Header",
        FontSize = 10,
        FontFamily = "Helvetica"
    };

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

    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 Header",
        FontSize = 10,
        FontFamily = "Helvetica"
    };

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

    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 Header",
        .FontSize = 10,
        .FontFamily = "Helvetica"
    }

    renderer.RenderingOptions.TextFooter = New TextHeaderFooter With {
        .CenterText = "Page {page} of {total-pages}",
        .FontSize = 10,
        .FontFamily = "Helvetica"
    }

    Using pdf = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs(outputPath)
    End Using
End Sub
$vbLabelText   $csharpLabel

IronPDF gère automatiquement l'itération des pages et supporte les jetons de type {page} et {total-pages}. Pour des mises en page plus avancées, consultez la documentation sur les en-têtes et les pieds de page.

Conversion d'URL en PDF

Adobe PDF Library SDK n'intègre pas de fonction de rendu d'URL.IronPDF assure la prise en charge native :

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
$vbLabelText   $csharpLabel

Pour connaître l'ensemble des options de conversion d'URL, consultez la documentation sur les URL au format PDF.

Intégration d'ASP.NET Core

Le modèle d'initialisation statique d'Adobe PDF Library SDK crée des frictions avec l'injection de dépendances.IronPDFs'intègre naturellement aux architectures .NET modernes.

Adobe Pattern (problématique pour DI):

public class AdobePdfService
{
    public byte[] Generate(string content)
    {
        Library.Initialize();
        try
        {
            // Document complexeconstruction...
            return bytes;
        }
        finally
        {
            Library.Terminate();
        }
    }
}
public class AdobePdfService
{
    public byte[] Generate(string content)
    {
        Library.Initialize();
        try
        {
            // Document complexeconstruction...
            return bytes;
        }
        finally
        {
            Library.Terminate();
        }
    }
}
Public Class AdobePdfService
    Public Function Generate(content As String) As Byte()
        Library.Initialize()
        Try
            ' Document complex construction...
            Return bytes
        Finally
            Library.Terminate()
        End Try
    End Function
End Class
$vbLabelText   $csharpLabel

Modèle IronPDF(DI-Friendly):

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

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;
    }
}

// Register in Program.cs (.NET 6+):
builder.Services.AddSingleton<IPdfService, IronPdfService>();
public interface IPdfService
{
    Task<byte[]> GeneratePdfAsync(string html);
}

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;
    }
}

// Register in Program.cs (.NET 6+):
builder.Services.AddSingleton<IPdfService, IronPdfService>();
Imports System.Threading.Tasks

Public Interface IPdfService
    Function GeneratePdfAsync(html As String) As Task(Of Byte())
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
End Class

' Register in Program.vb (.NET 6+):
builder.Services.AddSingleton(Of IPdfService, IronPdfService)()
$vbLabelText   $csharpLabel

Support asynchrone

Adobe PDF Library SDK ne prend pas en charge les opérations asynchrones.IronPDF offre des fonctionnalités asynchrones/await complètes, essentielles pour les applications web évolutives :

public async Task<IActionResult> GenerateReport()
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}
public async Task<IActionResult> GenerateReport()
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc

Public Class ReportController
    Inherits Controller

    Public Async Function GenerateReport() As Task(Of IActionResult)
        Dim renderer As New ChromePdfRenderer()
        Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
            Return File(pdf.BinaryData, "application/pdf")
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Optimisation des performances

Comparaison de l'utilisation de la mémoire

Scénario Bibliothèque Adobe PDF SDK IronPDF
PDF simple ~100 MB ~50 MB
Document complexe ~200 MB ~80 MB
Lot (100 PDF) Haut (mémoire native) ~100 MB

Conseils d'optimisation

Réutiliser les instances de rendu :

// Good: Reuse renderer for batch operations
var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs($"output_{i}.pdf");
}
// Good: Reuse renderer for batch operations
var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs($"output_{i}.pdf");
}
' Good: Reuse renderer for batch operations
Dim renderer = New ChromePdfRenderer()
For Each html In htmlList
    Using pdf = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs($"output_{i}.pdf")
    End Using
Next
$vbLabelText   $csharpLabel

Utiliser Async dans les applications Web:

public async Task<IActionResult> GenerateReport()
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}
public async Task<IActionResult> GenerateReport()
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc

Public Class ReportController
    Inherits Controller

    Public Async Function GenerateReport() As Task(Of IActionResult)
        Dim renderer As New ChromePdfRenderer()
        Using pdf = Await renderer.RenderHtmlAsPdfAsync(html)
            Return File(pdf.BinaryData, "application/pdf")
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Dépannage des problèmes de migration courants

Sujet : Le positionnement par coordonnées ne fonctionne pas

Adobe utilise les coordonnées de points PostScript.IronPDF utilise le positionnement CSS :

// Adobe: Point-based
new TextRun("Hello", font, 12, new Point(100, 700));

// IronPDF: CSS-based
string html = "<p style='position:absolute; left:100px; top:92px;'>Hello</p>";
// Adobe: Point-based
new TextRun("Hello", font, 12, new Point(100, 700));

// IronPDF: CSS-based
string html = "<p style='position:absolute; left:100px; top:92px;'>Hello</p>";
' Adobe: Point-based
New TextRun("Hello", font, 12, New Point(100, 700))

' IronPDF: CSS-based
Dim html As String = "<p style='position:absolute; left:100px; top:92px;'>Hello</p>"
$vbLabelText   $csharpLabel

Sujet : Différences de taille de page

Adobe utilise des points PostScript.IronPDF utilise des enums ou des dimensions personnalisées :

// Adobe: Points
Rect(0, 0, 612, 792) // Letter

// IronPDF: Enum or custom
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// Or custom:
renderer.RenderingOptions.SetCustomPaperSizeInInches(8.5, 11);
// Adobe: Points
Rect(0, 0, 612, 792) // Letter

// IronPDF: Enum or custom
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// Or custom:
renderer.RenderingOptions.SetCustomPaperSizeInInches(8.5, 11);
' Adobe: Points
Rect(0, 0, 612, 792) ' Letter

' IronPDF: Enum or custom
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
' Or custom:
renderer.RenderingOptions.SetCustomPaperSizeInInches(8.5, 11)
$vbLabelText   $csharpLabel

Problème : Police introuvable

Adobe exige l'intégration manuelle des polices.IronPDF gère automatiquement les polices de caractères :

// IronPDF: Use web fonts if needed
string html = @"
<style>
    @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
    body { font-family: 'Roboto', sans-serif; }
</style>";
// IronPDF: Use web fonts if needed
string html = @"
<style>
    @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
    body { font-family: 'Roboto', sans-serif; }
</style>";
' IronPDF: Use web fonts if needed
Dim html As String = "
<style>
    @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
    body { font-family: 'Roboto', sans-serif; }
</style>"
$vbLabelText   $csharpLabel

Sujet : SaveFlags non disponible

Adobe utilise des combinaisons de drapeaux de sauvegarde.IronPDF utilise l'enregistrement direct :

// Adobe
doc.Save(SaveFlags.Full | SaveFlags.Incremental, path);

//IronPDF- full save is default
pdf.SaveAs(path);
// Adobe
doc.Save(SaveFlags.Full | SaveFlags.Incremental, path);

//IronPDF- full save is default
pdf.SaveAs(path);
$vbLabelText   $csharpLabel

Liste de contrôle post-migration

Après avoir effectué la migration du code, vérifiez les points suivants :

  • Exécuter tous les tests unitaires et d'intégration existants
  • Comparer visuellement les fichiers PDF générés avec les versions précédentes
  • Tester tous les flux de travail PDF dans un environnement de test
  • Vérifiez que la licence fonctionne correctement (IronPdf.License.IsLicensed)
  • Évaluation comparative des performances par rapport à l'implémentation précédente
  • Supprimer la configuration de licence Adobe
  • Mettre à jour les dépendances du pipeline CI/CD
  • Supprimez toutes les DLL de la bibliothèque Adobe PDF du projet
  • Documentez les nouveaux modèles pour votre équipe de développement

Ressources supplémentaires


Passer de l'APDFL à IronPDF peut simplifier la base de code typique de génération de PDF en .NET, notamment pour les équipes dont le besoin principal est la conversion HTML en PDF ou la manipulation de documents plutôt que la surface complète des fonctionnalités dérivées d'Acrobat. Le passage de la construction de pages à bas niveau au rendu HTML/CSS élimine la plupart des calculs de coordonnées, de la gestion des polices, et du code de gestion du cycle de vie Library, et la licence transparente d'IronPDF par développeur est généralement plus facile à budgétiser que le modèle basé sur les ventes, OEM/SaaS-royalty d'APDFL.

Veuillez noterAdobe, Acrobat, et Adobe PDF Library sont des marques déposées d'Adobe Inc. L'APDFL est distribué par Datalogics, Inc. sous licence d'Adobe. Ce site n'est pas affilié, approuvé ou sponsorisé par Adobe Inc. ou Datalogics, Inc. Tous les noms de produit, logos, et marques sont la propriété de leurs propriétaires respectifs. Les comparaisons sont à titre informatif uniquement et reflètent les informations publiquement disponibles au moment de l'écriture.

Curtis Chau
Rédacteur technique

Curtis Chau détient un baccalauréat en informatique (Université de Carleton) et se spécialise dans le développement front-end avec expertise en Node.js, TypeScript, JavaScript et React. Passionné par la création d'interfaces utilisateur intuitives et esthétiquement plaisantes, Curtis aime travailler avec des frameworks modernes ...

Lire la suite

Équipe de soutien Iron

Nous sommes en ligne 24 heures sur 24, 5 jours sur 7.
Chat
Email
Appelez-moi