產品比較

IronPDF 與 iText7 的比較

發佈 2024年8月11日
分享:

介紹

一個不錯且簡單的 PDF 操作工具可以簡化許多涉及創建和編輯 PDF 文件的任務和過程。在 .NET 生態系統中,有兩個流行的庫 - IronPDF 和 iText——允許在沒有任何 Adobe 依賴的情況下生成 PDF。它們都有各種功能,例如創建、編輯、轉換等,但本文將重點比較這些庫的三個標準:它們提供的功能能力、它們提供的文檔質量、這些公司採用的產品定價政策。

概述 IronPDF 和 iText

IronPDF 是一個顯著的 .NET PDF 庫,使程式員能輕鬆創建、修改和操作 PDF 文件。它可以在不同的 .NET 環境中使用,包括 Core、8、7、6 和 Framework,這使其在不同的開發需求中非常靈活。其主要特點 IronPDF 其豐富的功能集,例如 HTML轉 PDF, 合併 PDF的能力, PDF 加密以及應用數位簽名等。文檔的編寫方式使用戶可以毫不費力地理解,而該庫本身具有強大的技術支持。

iText 是 Java 以及 .NET 中最受歡迎的 PDF 庫 之一。 (C#)iText Core 8 提供企業級可編程解決方案,來創建和操作 PDF 文件。iText 支援許多不同的功能,並以開源方式發佈。 (AGPL) 許可證和商業許可證。這意味著,由於其多功能性,它能夠在數位轉型項目中涵蓋廣泛的使用案例。

跨平台相容性

IronPDF 和 iText 相容於多種平台;它們能在許多不同系統上處理 PDF,並且在 .NET 框架內也是如此。因此,我們將在下文比較每個產品所支援的框架和平台。

IronPDF:

IronPDF 支援廣泛的平台和環境,確保在各種系統中的無縫整合與部署:

  • .NET 版本:

    • (C#, VB.NET, F#)

    • .NET Core (8, 7, 6, 5, 和 3.1+)

    • .NET標準 (2.0+)
  • .NET Framework (4.6.2+)
  • 應用環境: IronPDF 適用於包括 Windows、Linux、Mac、Docker、Azure 和 AWS 在內的應用環境
  • 集成開發環境 (IDEs): 適用於 Microsoft Visual Studio 和 JetBrains Rider & ReSharper 等集成開發環境
  • 操作系統和處理器: 支援多種不同的操作系統和處理器,包括 Windows、Mac、Linux、x64、x86、ARM

iText

  • .NET 版本:

    • .NET Core (2.x, 3.x)

    • .NET Framework (4.6.1+)
  • .NET 5+
  • 應用環境: iText 支援多種應用環境,因為它同時支援 Java 和 .NET (C#),這些包括:Windows、Mac、Linux,以及 Docker。

  • 操作系統:運行於 Windows、macOS 和 Linux 作業系統

關鍵功能比較:IronPDF vs. iText

IronPDF 和iText都提供了一系列可用於處理PDF檔案的功能和工具;接下來的這一部分將重點介紹其中的一些功能,以及這兩個庫在執行不同的PDF相關任務時的比較。

IronPDF

  • HTML 轉換為 PDF:支援 HTML、CSS、JavaScript 和圖像。
  • PDF 檔案操作:分割並合併文件,更改格式並編輯現有的 PDF 文件
  • 安全性:PDF 加密和解密。
  • 編輯:添加註釋、書籤和大綱。
  • 範本:應用頁首、頁尾和頁碼。
  • 浮水印:輕鬆地將文字和圖像浮水印應用於 PDF 文件,利用它的 HTML/CSS 功能來完全控制過程。

  • PDF 蓋章:使用 IronPDF 在 PDF 文件上蓋上圖像和文字。

有關 IronPDF 提供的豐富功能的更多信息,請訪問 IronPDF 功能頁面.

iText

  • PDF創建:支持從頭開始創建PDF文檔。
  • 表單:創建和編輯PDF表單。
  • 數字簽名:簽署PDF文檔。
  • 壓縮:優化PDF文件大小。
  • 內容提取:從PDF中提取文本和圖像。
  • 開源:在AGPL許可下提供。

  • 可定制性:針對高級使用情況的高度定制化。

IronPDF與iText之間PDF功能特性的比較

HTML 轉換為 PDF

轉換 將 HTML 內容轉換為 PDF 是一個在許多不同辦公室和工作空間中完成的非常簡單的任務。以下是比較 IronPDF 和 iText 如何處理這個過程的代碼示例。

IronPDF

using IronPdf;

// Disable local disk access or cross-origin requests
Installation.EnableWebSecurity = true;

// Instantiate Renderer
var renderer = new ChromePdfRenderer();

// Create a PDF from an HTML string using C#
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");

// Advanced Example with HTML Assets
// Load external html assets: images, CSS and JavaScript.
// An optional BasePath 'C:\site\assets\' is set as the file location to load assets from
var myAdvancedPdf = renderer.RenderHtmlAsPdf("<img src='icons/iron.png'>", @"C:\site\assets\");
myAdvancedPdf.SaveAs("html-with-assets.pdf");
using IronPdf;

// Disable local disk access or cross-origin requests
Installation.EnableWebSecurity = true;

// Instantiate Renderer
var renderer = new ChromePdfRenderer();

// Create a PDF from an HTML string using C#
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");

// Advanced Example with HTML Assets
// Load external html assets: images, CSS and JavaScript.
// An optional BasePath 'C:\site\assets\' is set as the file location to load assets from
var myAdvancedPdf = renderer.RenderHtmlAsPdf("<img src='icons/iron.png'>", @"C:\site\assets\");
myAdvancedPdf.SaveAs("html-with-assets.pdf");
Imports IronPdf

' Disable local disk access or cross-origin requests
Installation.EnableWebSecurity = True

' Instantiate Renderer
Dim renderer = New ChromePdfRenderer()

' Create a PDF from an HTML string using C#
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>")
pdf.SaveAs("output.pdf")

' Advanced Example with HTML Assets
' Load external html assets: images, CSS and JavaScript.
' An optional BasePath 'C:\site\assets\' is set as the file location to load assets from
Dim myAdvancedPdf = renderer.RenderHtmlAsPdf("<img src='icons/iron.png'>", "C:\site\assets\")
myAdvancedPdf.SaveAs("html-with-assets.pdf")
VB   C#

iText

using iText.Html2pdf;

static void Main(string[] args)
  {
    using (FileStream htmlSource = File.Open("input.html", FileMode.Open))
    using (FileStream pdfDest = File.Open("output.pdf", FileMode.Create))
    {
        ConverterProperties converterProperties = new ConverterProperties();
        HtmlConverter.ConvertToPdf(htmlSource, pdfDest, converterProperties);
    }
  }
using iText.Html2pdf;

static void Main(string[] args)
  {
    using (FileStream htmlSource = File.Open("input.html", FileMode.Open))
    using (FileStream pdfDest = File.Open("output.pdf", FileMode.Create))
    {
        ConverterProperties converterProperties = new ConverterProperties();
        HtmlConverter.ConvertToPdf(htmlSource, pdfDest, converterProperties);
    }
  }
Imports iText.Html2pdf

Shared Sub Main(ByVal args() As String)
	Using htmlSource As FileStream = File.Open("input.html", FileMode.Open)
	Using pdfDest As FileStream = File.Open("output.pdf", FileMode.Create)
		Dim converterProperties As New ConverterProperties()
		HtmlConverter.ConvertToPdf(htmlSource, pdfDest, converterProperties)
	End Using
	End Using
End Sub
VB   C#

在將 HTML 轉換為 PDF 時,IronPDF 提供了一個簡潔方便的工具來執行這項任務。利用 ChromePdfRenderer 將 HTML 內容轉換成 PDF,IronPDF 專注於為用戶提供像素完美的 PDF 文件。用戶可以直接從 HTML 字串創建 PDF,如第一個範例所示,或使用可選的基底路徑包含外部資源如圖片,如進階範例中展示的。iText 採用的是基本方法,使用其 HtmlConverter 類別從 HTML 文件創建 PDF 文件。

加密 PDF 文件

加密 在許多工作場所中,加密和解密 PDF 文件是至關重要的。為了輕鬆完成這項任務,有一個方便的工具是必須的。在下面的代碼中,我們將看到 iText 和 IronPDF 如何處理 PDF 的加密。

IronPDF

using IronPdf;
using System;

// Open an Encrypted File, alternatively create a new PDF from Html
var pdf = PdfDocument.FromFile("encrypted.pdf", "password");

// Edit file metadata
pdf.MetaData.Author = "Satoshi Nakamoto";
pdf.MetaData.Keywords = "SEO, Friendly";
pdf.MetaData.ModifiedDate = DateTime.Now;

// Edit file security settings
// The following code makes a PDF read only and will disallow copy & paste and printing
pdf.SecuritySettings.RemovePasswordsAndEncryption();
pdf.SecuritySettings.MakePdfDocumentReadOnly("secret-key");
pdf.SecuritySettings.AllowUserAnnotations = false;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserFormData = false;
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.FullPrintRights;

// change or set the document encryption password
pdf.Password = "my-password";
pdf.SaveAs("secured.pdf");
using IronPdf;
using System;

// Open an Encrypted File, alternatively create a new PDF from Html
var pdf = PdfDocument.FromFile("encrypted.pdf", "password");

// Edit file metadata
pdf.MetaData.Author = "Satoshi Nakamoto";
pdf.MetaData.Keywords = "SEO, Friendly";
pdf.MetaData.ModifiedDate = DateTime.Now;

// Edit file security settings
// The following code makes a PDF read only and will disallow copy & paste and printing
pdf.SecuritySettings.RemovePasswordsAndEncryption();
pdf.SecuritySettings.MakePdfDocumentReadOnly("secret-key");
pdf.SecuritySettings.AllowUserAnnotations = false;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserFormData = false;
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.FullPrintRights;

// change or set the document encryption password
pdf.Password = "my-password";
pdf.SaveAs("secured.pdf");
Imports IronPdf
Imports System

' Open an Encrypted File, alternatively create a new PDF from Html
Private pdf = PdfDocument.FromFile("encrypted.pdf", "password")

' Edit file metadata
pdf.MetaData.Author = "Satoshi Nakamoto"
pdf.MetaData.Keywords = "SEO, Friendly"
pdf.MetaData.ModifiedDate = DateTime.Now

' Edit file security settings
' The following code makes a PDF read only and will disallow copy & paste and printing
pdf.SecuritySettings.RemovePasswordsAndEncryption()
pdf.SecuritySettings.MakePdfDocumentReadOnly("secret-key")
pdf.SecuritySettings.AllowUserAnnotations = False
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserFormData = False
pdf.SecuritySettings.AllowUserPrinting = IronPdf.Security.PdfPrintSecurity.FullPrintRights

' change or set the document encryption password
pdf.Password = "my-password"
pdf.SaveAs("secured.pdf")
VB   C#

iText

using System;
using System.IO;
using System.Text;
using iText.Kernel.Pdf;

public class EncryptPdf
    {
        public static readonly String DEST = "results/sandbox/security/encrypt_pdf.pdf";
        public static readonly String SRC = "../../../resources/pdfs/hello.pdf";

        public static readonly String OWNER_PASSWORD = "World";
        public static readonly String USER_PASSWORD = "Hello";

        public static void Main(String[] args)
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new EncryptPdf().ManipulatePdf(DEST);
        }

        protected void ManipulatePdf(String dest)
        {
            PdfDocument document = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest,
                new WriterProperties().SetStandardEncryption(
                    Encoding.UTF8.GetBytes(USER_PASSWORD),
                    Encoding.UTF8.GetBytes(OWNER_PASSWORD),
                    EncryptionConstants.ALLOW_PRINTING,
                    EncryptionConstants.ENCRYPTION_AES_128 
 EncryptionConstants.DO_NOT_ENCRYPT_METADATA
                )));
            document.Close();
        }
    }
using System;
using System.IO;
using System.Text;
using iText.Kernel.Pdf;

public class EncryptPdf
    {
        public static readonly String DEST = "results/sandbox/security/encrypt_pdf.pdf";
        public static readonly String SRC = "../../../resources/pdfs/hello.pdf";

        public static readonly String OWNER_PASSWORD = "World";
        public static readonly String USER_PASSWORD = "Hello";

        public static void Main(String[] args)
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new EncryptPdf().ManipulatePdf(DEST);
        }

        protected void ManipulatePdf(String dest)
        {
            PdfDocument document = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest,
                new WriterProperties().SetStandardEncryption(
                    Encoding.UTF8.GetBytes(USER_PASSWORD),
                    Encoding.UTF8.GetBytes(OWNER_PASSWORD),
                    EncryptionConstants.ALLOW_PRINTING,
                    EncryptionConstants.ENCRYPTION_AES_128 
 EncryptionConstants.DO_NOT_ENCRYPT_METADATA
                )));
            document.Close();
        }
    }
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

IronPDF 提供用戶一個簡單明瞭的方式來加密PDF文件,同時也給予用戶高度的控制,包括編輯元數據和調整安全設置,例如將文件設置為只讀或限制用戶行為如複製和貼上。另一方面,iText 採用了較低層次且耗時更長的方法,在文件創建過程中應用PDF加密,指定擁有者和用戶的密碼,以及使用AES-128等加密標準來設置如打印權限等許可。

編輯 PDF 內容

處理機密或私人資訊時,偶爾可能需要 編輯 部分 PDF 文件的內容。以下的代碼範例將展示如何使用 IronPDF 與 iText 來編輯文本。

IronPDF

using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("novel.pdf");

// Redact 'are' phrase from all pages
pdf.RedactTextOnAllPages("are");

pdf.SaveAs("redacted.pdf");
using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("novel.pdf");

// Redact 'are' phrase from all pages
pdf.RedactTextOnAllPages("are");

pdf.SaveAs("redacted.pdf");
Imports IronPdf

Private pdf As PdfDocument = PdfDocument.FromFile("novel.pdf")

' Redact 'are' phrase from all pages
pdf.RedactTextOnAllPages("are")

pdf.SaveAs("redacted.pdf")
VB   C#

iText

using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Kernel.Colors;

string src = "input.pdf";
string dest = "output_redacted.pdf";

using (PdfReader reader = new PdfReader(src))
            {
                using (PdfWriter writer = new PdfWriter(dest))
                {
                    using (PdfDocument pdfDoc = new PdfDocument(reader, writer))
                    {
                        // Iterate through each page
                        for (int pageNum = 1; pageNum <= pdfDoc.GetNumberOfPages(); pageNum++)
                        {
                            PdfPage page = pdfDoc.GetPage(pageNum);
                            PdfCanvas canvas = new PdfCanvas(page);
                            Rectangle[] rectanglesToRedact = { new Rectangle(100, 100, 200, 50) }; // Example: Define rectangles to redact

                            // Overlay black rectangles to simulate redaction
                            foreach (Rectangle rect in rectanglesToRedact)
                            {
                                canvas.SetFillColor(ColorConstants.BLACK)
                                    .Rectangle(rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight())
                                    .Fill();
                            }
                        }
                    }
                }
using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Kernel.Colors;

string src = "input.pdf";
string dest = "output_redacted.pdf";

using (PdfReader reader = new PdfReader(src))
            {
                using (PdfWriter writer = new PdfWriter(dest))
                {
                    using (PdfDocument pdfDoc = new PdfDocument(reader, writer))
                    {
                        // Iterate through each page
                        for (int pageNum = 1; pageNum <= pdfDoc.GetNumberOfPages(); pageNum++)
                        {
                            PdfPage page = pdfDoc.GetPage(pageNum);
                            PdfCanvas canvas = new PdfCanvas(page);
                            Rectangle[] rectanglesToRedact = { new Rectangle(100, 100, 200, 50) }; // Example: Define rectangles to redact

                            // Overlay black rectangles to simulate redaction
                            foreach (Rectangle rect in rectanglesToRedact)
                            {
                                canvas.SetFillColor(ColorConstants.BLACK)
                                    .Rectangle(rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight())
                                    .Fill();
                            }
                        }
                    }
                }
Imports System
Imports System.IO
Imports iText.Kernel.Pdf
Imports iText.Layout
Imports iText.Layout.Element
Imports iText.Layout.Properties
Imports iText.Kernel.Colors

Private src As String = "input.pdf"
Private dest As String = "output_redacted.pdf"

Using reader As New PdfReader(src)
				Using writer As New PdfWriter(dest)
					Using pdfDoc As New PdfDocument(reader, writer)
						' Iterate through each page
						Dim pageNum As Integer = 1
						Do While pageNum <= pdfDoc.GetNumberOfPages()
							Dim page As PdfPage = pdfDoc.GetPage(pageNum)
							Dim canvas As New PdfCanvas(page)
							Dim rectanglesToRedact() As Rectangle = { New Rectangle(100, 100, 200, 50) } ' Example: Define rectangles to redact

							' Overlay black rectangles to simulate redaction
							For Each rect As Rectangle In rectanglesToRedact
								canvas.SetFillColor(ColorConstants.BLACK).Rectangle(rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight()).Fill()
							Next rect
							pageNum += 1
						Loop
					End Using
				End Using
VB   C#

IronPDF 的編輯工具簡潔易用,只需幾行程式碼即可簡化編輯流程。這有助於提高 PDF 編輯任務的效率,並為用戶提供了一種簡單的方法來保護他們的敏感和私人數據。

iText,另一方面,並不像 IronPDF 那樣提供內建的編輯工具。然而,它仍然可以使用上面所示的方法來覆蓋使用者希望編輯的內容。然而,這可能會引發問題,因為這些矩形並沒有實際移除或正確編輯文本,這意味著其他人可能會複製和粘貼試圖被編輯的數據。

簽署PDF文件

能夠 標誌 將數位文件(例如PDF文件)進行自動化處理可以節省時間。以下是一些代碼段,將比較IronPDF與iText在進行文件數位簽名方面的差異。

IronPDF

using IronPdf;
using IronPdf.Signing;
using System.Security.Cryptography.X509Certificates;

// Create X509Certificate2 object with X509KeyStorageFlags set to Exportable
X509Certificate2 cert = new X509Certificate2("IronSoftware.pfx", "123456", X509KeyStorageFlags.Exportable);

// Create PdfSignature object
var sig = new PdfSignature(cert);

// Sign PDF document
PdfDocument pdf = PdfDocument.FromFile("document.pdf");
pdf.Sign(sig);
pdf.SaveAs("signed.pdf");
using IronPdf;
using IronPdf.Signing;
using System.Security.Cryptography.X509Certificates;

// Create X509Certificate2 object with X509KeyStorageFlags set to Exportable
X509Certificate2 cert = new X509Certificate2("IronSoftware.pfx", "123456", X509KeyStorageFlags.Exportable);

// Create PdfSignature object
var sig = new PdfSignature(cert);

// Sign PDF document
PdfDocument pdf = PdfDocument.FromFile("document.pdf");
pdf.Sign(sig);
pdf.SaveAs("signed.pdf");
Imports IronPdf
Imports IronPdf.Signing
Imports System.Security.Cryptography.X509Certificates

' Create X509Certificate2 object with X509KeyStorageFlags set to Exportable
Private cert As New X509Certificate2("IronSoftware.pfx", "123456", X509KeyStorageFlags.Exportable)

' Create PdfSignature object
Private sig = New PdfSignature(cert)

' Sign PDF document
Private pdf As PdfDocument = PdfDocument.FromFile("document.pdf")
pdf.Sign(sig)
pdf.SaveAs("signed.pdf")
VB   C#

iText

using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;

class Program
{
    static void Main(string[] args)
    {
        string src = "input.pdf";
        string dest = "output_signed.pdf";
        string pfxFile = "your_certificate.pfx";
        string pfxPassword = "your_password";

        try
        {
            // Load your certificate
            Pkcs12Store ks = new Pkcs12Store(new FileStream(pfxFile, FileMode.Open), pfxPassword.ToCharArray());
            string alias = null;
            foreach (string al in ks.Aliases)
            {
                if (ks.IsKeyEntry(al))
                {
                    alias = al;
                    break;
                }
            }
            ICipherParameters pk = ks.GetKey(alias).Key;
            X509CertificateEntry[] chain = ks.GetCertificateChain(alias);
            X509Certificate2 cert = new X509Certificate2(chain[0].Certificate.GetEncoded());

            // Create output PDF with signed content
            using (PdfReader reader = new PdfReader(src))
            {
                using (PdfWriter writer = new PdfWriter(dest))
                {
                    using (PdfDocument pdfDoc = new PdfDocument(reader, writer))
                    {
                        // Create the signer
                        PdfSigner signer = new PdfSigner(pdfDoc, writer, new StampingProperties().UseAppendMode());

                        // Configure signature appearance
                        PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
                        appearance.SetReason("Digital Signature");
                        appearance.SetLocation("Your Location");
                        appearance.SetContact("Your Contact");

                        // Create signature
                        IExternalSignature pks = new PrivateKeySignature(pk, "SHA-256");
                        signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
                    }
                }
            }
            Console.WriteLine($"PDF digitally signed successfully: {dest}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error signing PDF: {ex.Message}");
        }
    }
}
using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;

class Program
{
    static void Main(string[] args)
    {
        string src = "input.pdf";
        string dest = "output_signed.pdf";
        string pfxFile = "your_certificate.pfx";
        string pfxPassword = "your_password";

        try
        {
            // Load your certificate
            Pkcs12Store ks = new Pkcs12Store(new FileStream(pfxFile, FileMode.Open), pfxPassword.ToCharArray());
            string alias = null;
            foreach (string al in ks.Aliases)
            {
                if (ks.IsKeyEntry(al))
                {
                    alias = al;
                    break;
                }
            }
            ICipherParameters pk = ks.GetKey(alias).Key;
            X509CertificateEntry[] chain = ks.GetCertificateChain(alias);
            X509Certificate2 cert = new X509Certificate2(chain[0].Certificate.GetEncoded());

            // Create output PDF with signed content
            using (PdfReader reader = new PdfReader(src))
            {
                using (PdfWriter writer = new PdfWriter(dest))
                {
                    using (PdfDocument pdfDoc = new PdfDocument(reader, writer))
                    {
                        // Create the signer
                        PdfSigner signer = new PdfSigner(pdfDoc, writer, new StampingProperties().UseAppendMode());

                        // Configure signature appearance
                        PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
                        appearance.SetReason("Digital Signature");
                        appearance.SetLocation("Your Location");
                        appearance.SetContact("Your Contact");

                        // Create signature
                        IExternalSignature pks = new PrivateKeySignature(pk, "SHA-256");
                        signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
                    }
                }
            }
            Console.WriteLine($"PDF digitally signed successfully: {dest}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error signing PDF: {ex.Message}");
        }
    }
}
Imports System
Imports System.IO
Imports iText.Kernel.Pdf
Imports iText.Signatures
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Pkcs
Imports Org.BouncyCastle.X509

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim src As String = "input.pdf"
		Dim dest As String = "output_signed.pdf"
		Dim pfxFile As String = "your_certificate.pfx"
		Dim pfxPassword As String = "your_password"

		Try
			' Load your certificate
			Dim ks As New Pkcs12Store(New FileStream(pfxFile, FileMode.Open), pfxPassword.ToCharArray())
			Dim [alias] As String = Nothing
			For Each al As String In ks.Aliases
				If ks.IsKeyEntry(al) Then
					[alias] = al
					Exit For
				End If
			Next al
			Dim pk As ICipherParameters = ks.GetKey([alias]).Key
			Dim chain() As X509CertificateEntry = ks.GetCertificateChain([alias])
			Dim cert As New X509Certificate2(chain(0).Certificate.GetEncoded())

			' Create output PDF with signed content
			Using reader As New PdfReader(src)
				Using writer As New PdfWriter(dest)
					Using pdfDoc As New PdfDocument(reader, writer)
						' Create the signer
						Dim signer As New PdfSigner(pdfDoc, writer, (New StampingProperties()).UseAppendMode())

						' Configure signature appearance
						Dim appearance As PdfSignatureAppearance = signer.GetSignatureAppearance()
						appearance.SetReason("Digital Signature")
						appearance.SetLocation("Your Location")
						appearance.SetContact("Your Contact")

						' Create signature
						Dim pks As IExternalSignature = New PrivateKeySignature(pk, "SHA-256")
						signer.SignDetached(pks, chain, Nothing, Nothing, Nothing, 0, PdfSigner.CryptoStandard.CMS)
					End Using
				End Using
			End Using
			Console.WriteLine($"PDF digitally signed successfully: {dest}")
		Catch ex As Exception
			Console.WriteLine($"Error signing PDF: {ex.Message}")
		End Try
	End Sub
End Class
VB   C#

在數位簽名PDF檔案時,IronPDF 提供了一個精簡但強大的工具來完成這一過程。其簡單性允許快速進行這一過程,為任何需要簽名的開發者節省了時間。iText 需要更長且更複雜的過程來應用數位簽名到PDF檔案上,儘管其可使用不同的介面選項和密鑰提供給用戶更多的控制,但該工具執行此任務的複雜性可能會成為阻礙。

為 PDF 文件應用浮水印

添加和個性化浮水印的能力 浮水印 通過軟件處理PDF可以極大地幫助保密、版權保護、品牌或任何涉及敏感信息的任務。以下是IronPDF和iText對PDF文件添加水印的比較。

IronPDF

using IronPdf;

// Stamps a Watermark onto a new or existing PDF
var renderer = new ChromePdfRenderer();

var pdf = renderer.RenderUrlAsPdf("https://www.nuget.org/packages/IronPdf");
pdf.ApplyWatermark("<h2 style='color:red'>SAMPLE</h2>", 30, IronPdf.Editing.VerticalAlignment.Middle, IronPdf.Editing.HorizontalAlignment.Center);
pdf.SaveAs(@"C:\Path\To\Watermarked.pdf");
using IronPdf;

// Stamps a Watermark onto a new or existing PDF
var renderer = new ChromePdfRenderer();

var pdf = renderer.RenderUrlAsPdf("https://www.nuget.org/packages/IronPdf");
pdf.ApplyWatermark("<h2 style='color:red'>SAMPLE</h2>", 30, IronPdf.Editing.VerticalAlignment.Middle, IronPdf.Editing.HorizontalAlignment.Center);
pdf.SaveAs(@"C:\Path\To\Watermarked.pdf");
Imports IronPdf

' Stamps a Watermark onto a new or existing PDF
Private renderer = New ChromePdfRenderer()

Private pdf = renderer.RenderUrlAsPdf("https://www.nuget.org/packages/IronPdf")
pdf.ApplyWatermark("<h2 style='color:red'>SAMPLE</h2>", 30, IronPdf.Editing.VerticalAlignment.Middle, IronPdf.Editing.HorizontalAlignment.Center)
pdf.SaveAs("C:\Path\To\Watermarked.pdf")
VB   C#

iText

using iText.IO.Font;
using iText.IO.Font.Constants;
using iText.Kernel.Colors;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Kernel.Pdf.Extgstate;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;

public class TransparentWatermark 
    {
        public static readonly String DEST = "results/sandbox/stamper/transparent_watermark.pdf";
        public static readonly String SRC = "../../../resources/pdfs/hero.pdf";

        public static void Main(String[] args) 
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new TransparentWatermark().ManipulatePdf(DEST);
        }

        protected void ManipulatePdf(String dest) 
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
            PdfCanvas under = new PdfCanvas(pdfDoc.GetFirstPage().NewContentStreamBefore(), new PdfResources(), pdfDoc);
            PdfFont font = PdfFontFactory.CreateFont(FontProgramFactory.CreateFont(StandardFonts.HELVETICA));
            Paragraph paragraph = new Paragraph("This watermark is added UNDER the existing content")
                    .SetFont(font)
                    .SetFontSize(15);

            Canvas canvasWatermark1 = new Canvas(under, pdfDoc.GetDefaultPageSize())
                    .ShowTextAligned(paragraph, 297, 550, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
            canvasWatermark1.Close();
            PdfCanvas over = new PdfCanvas(pdfDoc.GetFirstPage());
            over.SetFillColor(ColorConstants.BLACK);
            paragraph = new Paragraph("This watermark is added ON TOP OF the existing content")
                    .SetFont(font)
                    .SetFontSize(15);

            Canvas canvasWatermark2 = new Canvas(over, pdfDoc.GetDefaultPageSize())
                    .ShowTextAligned(paragraph, 297, 500, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
            canvasWatermark2.Close();
            paragraph = new Paragraph("This TRANSPARENT watermark is added ON TOP OF the existing content")
                    .SetFont(font)
                    .SetFontSize(15);
            over.SaveState();

            // Creating a dictionary that maps resource names to graphics state parameter dictionaries
            PdfExtGState gs1 = new PdfExtGState();
            gs1.SetFillOpacity(0.5f);
            over.SetExtGState(gs1);
            Canvas canvasWatermark3 = new Canvas(over, pdfDoc.GetDefaultPageSize())
                    .ShowTextAligned(paragraph, 297, 450, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
            canvasWatermark3.Close();
            over.RestoreState();

            pdfDoc.Close();
        }
    }
using iText.IO.Font;
using iText.IO.Font.Constants;
using iText.Kernel.Colors;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Kernel.Pdf.Extgstate;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;

public class TransparentWatermark 
    {
        public static readonly String DEST = "results/sandbox/stamper/transparent_watermark.pdf";
        public static readonly String SRC = "../../../resources/pdfs/hero.pdf";

        public static void Main(String[] args) 
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new TransparentWatermark().ManipulatePdf(DEST);
        }

        protected void ManipulatePdf(String dest) 
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
            PdfCanvas under = new PdfCanvas(pdfDoc.GetFirstPage().NewContentStreamBefore(), new PdfResources(), pdfDoc);
            PdfFont font = PdfFontFactory.CreateFont(FontProgramFactory.CreateFont(StandardFonts.HELVETICA));
            Paragraph paragraph = new Paragraph("This watermark is added UNDER the existing content")
                    .SetFont(font)
                    .SetFontSize(15);

            Canvas canvasWatermark1 = new Canvas(under, pdfDoc.GetDefaultPageSize())
                    .ShowTextAligned(paragraph, 297, 550, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
            canvasWatermark1.Close();
            PdfCanvas over = new PdfCanvas(pdfDoc.GetFirstPage());
            over.SetFillColor(ColorConstants.BLACK);
            paragraph = new Paragraph("This watermark is added ON TOP OF the existing content")
                    .SetFont(font)
                    .SetFontSize(15);

            Canvas canvasWatermark2 = new Canvas(over, pdfDoc.GetDefaultPageSize())
                    .ShowTextAligned(paragraph, 297, 500, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
            canvasWatermark2.Close();
            paragraph = new Paragraph("This TRANSPARENT watermark is added ON TOP OF the existing content")
                    .SetFont(font)
                    .SetFontSize(15);
            over.SaveState();

            // Creating a dictionary that maps resource names to graphics state parameter dictionaries
            PdfExtGState gs1 = new PdfExtGState();
            gs1.SetFillOpacity(0.5f);
            over.SetExtGState(gs1);
            Canvas canvasWatermark3 = new Canvas(over, pdfDoc.GetDefaultPageSize())
                    .ShowTextAligned(paragraph, 297, 450, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0);
            canvasWatermark3.Close();
            over.RestoreState();

            pdfDoc.Close();
        }
    }
Imports iText.IO.Font
Imports iText.IO.Font.Constants
Imports iText.Kernel.Colors
Imports iText.Kernel.Font
Imports iText.Kernel.Pdf
Imports iText.Kernel.Pdf.Canvas
Imports iText.Kernel.Pdf.Extgstate
Imports iText.Layout
Imports iText.Layout.Element
Imports iText.Layout.Properties

Public Class TransparentWatermark
		Public Shared ReadOnly DEST As String = "results/sandbox/stamper/transparent_watermark.pdf"
		Public Shared ReadOnly SRC As String = "../../../resources/pdfs/hero.pdf"

		Public Shared Sub Main(ByVal args() As String)
			Dim file As New FileInfo(DEST)
			file.Directory.Create()

			Call (New TransparentWatermark()).ManipulatePdf(DEST)
		End Sub

		Protected Sub ManipulatePdf(ByVal dest As String)
			Dim pdfDoc As New PdfDocument(New PdfReader(SRC), New PdfWriter(dest))
			Dim under As New PdfCanvas(pdfDoc.GetFirstPage().NewContentStreamBefore(), New PdfResources(), pdfDoc)
			Dim font As PdfFont = PdfFontFactory.CreateFont(FontProgramFactory.CreateFont(StandardFonts.HELVETICA))
			Dim paragraph As Paragraph = (New Paragraph("This watermark is added UNDER the existing content")).SetFont(font).SetFontSize(15)

			Dim canvasWatermark1 As Canvas = (New Canvas(under, pdfDoc.GetDefaultPageSize())).ShowTextAligned(paragraph, 297, 550, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0)
			canvasWatermark1.Close()
			Dim over As New PdfCanvas(pdfDoc.GetFirstPage())
			over.SetFillColor(ColorConstants.BLACK)
			paragraph = (New Paragraph("This watermark is added ON TOP OF the existing content")).SetFont(font).SetFontSize(15)

			Dim canvasWatermark2 As Canvas = (New Canvas(over, pdfDoc.GetDefaultPageSize())).ShowTextAligned(paragraph, 297, 500, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0)
			canvasWatermark2.Close()
			paragraph = (New Paragraph("This TRANSPARENT watermark is added ON TOP OF the existing content")).SetFont(font).SetFontSize(15)
			over.SaveState()

			' Creating a dictionary that maps resource names to graphics state parameter dictionaries
			Dim gs1 As New PdfExtGState()
			gs1.SetFillOpacity(0.5F)
			over.SetExtGState(gs1)
			Dim canvasWatermark3 As Canvas = (New Canvas(over, pdfDoc.GetDefaultPageSize())).ShowTextAligned(paragraph, 297, 450, 1, TextAlignment.CENTER, VerticalAlignment.TOP, 0)
			canvasWatermark3.Close()
			over.RestoreState()

			pdfDoc.Close()
		End Sub
End Class
VB   C#

IronPDF 的簡單直觀 API 讓用戶能夠快速對 PDF 文件應用自定義水印,同時讓他們完整控制這個過程。其使用 HTML/CSS 進一步簡化了過程,且在自定義過程中不失控。 iText 添加水印到 PDF 的方法需要更多手動工作來完成此任務,這可能會減慢這一過程。

在 PDF 上打印圖像和文本

有時 PDF 頁面需要 已加章 將內容加蓋,比如一個人可能需要在他們的PDF文件上應用浮水印。我們現在將比較IronPDF和iText在PDF文件上加蓋內容的表現。

IronPDF

using IronPdf;
using IronPdf.Editing;

ChromePdfRenderer renderer = new ChromePdfRenderer();

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Example HTML Document!</h1>");

// Create text stamper
TextStamper textStamper = new TextStamper()
{
    Text = "Text Stamper!",
    FontFamily = "Bungee Spice",
    UseGoogleFont = true,
    FontSize = 30,
    IsBold = true,
    IsItalic = true,
    VerticalAlignment = VerticalAlignment.Top,
};

// Stamp the text stamper
pdf.ApplyStamp(textStamper);
pdf.SaveAs("stampText.pdf");

// Create image stamper
ImageStamper imageStamper = new ImageStamper(new Uri("https://ironpdf.com/img/svgs/iron-pdf-logo.svg"))
{
    VerticalAlignment = VerticalAlignment.Top,
};

// Stamp the image stamper
pdf.ApplyStamp(imageStamper, 0);
pdf.SaveAs("stampImage.pdf");
using IronPdf;
using IronPdf.Editing;

ChromePdfRenderer renderer = new ChromePdfRenderer();

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Example HTML Document!</h1>");

// Create text stamper
TextStamper textStamper = new TextStamper()
{
    Text = "Text Stamper!",
    FontFamily = "Bungee Spice",
    UseGoogleFont = true,
    FontSize = 30,
    IsBold = true,
    IsItalic = true,
    VerticalAlignment = VerticalAlignment.Top,
};

// Stamp the text stamper
pdf.ApplyStamp(textStamper);
pdf.SaveAs("stampText.pdf");

// Create image stamper
ImageStamper imageStamper = new ImageStamper(new Uri("https://ironpdf.com/img/svgs/iron-pdf-logo.svg"))
{
    VerticalAlignment = VerticalAlignment.Top,
};

// Stamp the image stamper
pdf.ApplyStamp(imageStamper, 0);
pdf.SaveAs("stampImage.pdf");
Imports IronPdf
Imports IronPdf.Editing

Private renderer As New ChromePdfRenderer()

Private pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>Example HTML Document!</h1>")

' Create text stamper
Private textStamper As New TextStamper() With {
	.Text = "Text Stamper!",
	.FontFamily = "Bungee Spice",
	.UseGoogleFont = True,
	.FontSize = 30,
	.IsBold = True,
	.IsItalic = True,
	.VerticalAlignment = VerticalAlignment.Top
}

' Stamp the text stamper
pdf.ApplyStamp(textStamper)
pdf.SaveAs("stampText.pdf")

' Create image stamper
Dim imageStamper As New ImageStamper(New Uri("https://ironpdf.com/img/svgs/iron-pdf-logo.svg")) With {.VerticalAlignment = VerticalAlignment.Top}

' Stamp the image stamper
pdf.ApplyStamp(imageStamper, 0)
pdf.SaveAs("stampImage.pdf")
VB   C#

iText

using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;

public void StampPDF(string inputPdfPath, string outputPdfPath, string stampText)
{
    PdfDocument pdfDoc = new PdfDocument(new PdfReader(inputPdfPath), new PdfWriter(outputPdfPath));

    Document doc = new Document(pdfDoc);

    // Add stamp (text) to each page
    int numPages = pdfDoc.GetNumberOfPages();
    for (int i = 1; i <= numPages; i++)
    {
        doc.ShowTextAligned(new Paragraph(stampText),
                            36, 36, i, iText.Layout.Properties.TextAlignment.LEFT,
                            iText.Layout.Properties.VerticalAlignment.TOP, 0);
    }

    doc.Close();
}
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;

public void StampPDF(string inputPdfPath, string outputPdfPath, string stampText)
{
    PdfDocument pdfDoc = new PdfDocument(new PdfReader(inputPdfPath), new PdfWriter(outputPdfPath));

    Document doc = new Document(pdfDoc);

    // Add stamp (text) to each page
    int numPages = pdfDoc.GetNumberOfPages();
    for (int i = 1; i <= numPages; i++)
    {
        doc.ShowTextAligned(new Paragraph(stampText),
                            36, 36, i, iText.Layout.Properties.TextAlignment.LEFT,
                            iText.Layout.Properties.VerticalAlignment.TOP, 0);
    }

    doc.Close();
}
Imports iText.Kernel.Pdf
Imports iText.Layout
Imports iText.Layout.Element

Public Sub StampPDF(ByVal inputPdfPath As String, ByVal outputPdfPath As String, ByVal stampText As String)
	Dim pdfDoc As New PdfDocument(New PdfReader(inputPdfPath), New PdfWriter(outputPdfPath))

	Dim doc As New Document(pdfDoc)

	' Add stamp (text) to each page
	Dim numPages As Integer = pdfDoc.GetNumberOfPages()
	For i As Integer = 1 To numPages
		doc.ShowTextAligned(New Paragraph(stampText), 36, 36, i, iText.Layout.Properties.TextAlignment.LEFT, iText.Layout.Properties.VerticalAlignment.TOP, 0)
	Next i

	doc.Close()
End Sub
VB   C#

IronPDF 可以幫助您將文字或圖像添加到 PDF 中,其方式非常靈活且可定制;讓您完全掌控。API 容易理解和操作,特別是對熟悉 HTML/CSS 的開發人員來說。iText 利用其圖像和文字蓋章工具,讓用戶更能掌控在 PDF 文件上顯示的內容,儘管這個過程可能會更手動。

將 DOCX 轉換為 PDF

有時候,您可能需要將 PDF 從一種格式轉換為另一種格式。在這種情況下,我們正在查看 DOCX轉PDF轉換 並比較 IronPDF 和 iText 如何以不同方式處理此過程。

IronPDF

using IronPdf;

// Instantiate Renderer
DocxToPdfRenderer renderer = new DocxToPdfRenderer();

// Render from DOCX file
PdfDocument pdf = renderer.RenderDocxAsPdf("Modern-chronological-resume.docx");

// Save the PDF
pdf.SaveAs("pdfFromDocx.pdf");
using IronPdf;

// Instantiate Renderer
DocxToPdfRenderer renderer = new DocxToPdfRenderer();

// Render from DOCX file
PdfDocument pdf = renderer.RenderDocxAsPdf("Modern-chronological-resume.docx");

// Save the PDF
pdf.SaveAs("pdfFromDocx.pdf");
Imports IronPdf

' Instantiate Renderer
Private renderer As New DocxToPdfRenderer()

' Render from DOCX file
Private pdf As PdfDocument = renderer.RenderDocxAsPdf("Modern-chronological-resume.docx")

' Save the PDF
pdf.SaveAs("pdfFromDocx.pdf")
VB   C#

iText

iText本身無法處理DOCX轉PDF的轉換;相反地,它依賴於外部庫,如DocX或Aspose.Words。

IronPDF為開發人員提供了一個簡單明瞭的工具,用於處理DOCX轉PDF轉換任務,使得將DOCX檔案轉換為PDF格式變得輕而易舉,無需外部庫。而iText則依賴外部庫來完成該任務。

程式範例比較摘要

如需更詳細的示例,請訪問 IronPDF 範例.

定價和授權:IronPDF 與 iText 庫比較

IronPDF 價格與授權

IronPDF 具有不同层级和额外功能的许可证可供购买。开发人员还可以购买 IronSuite ,讓您以兩個產品的價格獲得所有IronSoftware的產品。如果您還沒準備購買授權,IronPDF提供 免費試用 30天。

  • 永久授權:根據團隊規模、專案需求和地點數量,提供一系列永久授權。每種類型的授權都會附帶電子郵件支援。
  • Lite License:此授權費用為$749美元,支援一名開發人員、一個地點和一個專案。
  • Plus License:支援三名開發人員、三個地點和三個專案,這是Lite License的升級版,費用為$1,499美元。Plus License除了基本的電子郵件支援外,還提供聊天支援和電話支援。
  • Professional License:此授權適合較大型團隊,支援十名開發人員、十個地點和十個專案,費用為$2,999美元。它提供與前一級相同的聯絡支援渠道,還包括螢幕分享支援。
  • 免版稅再分發:IronPDF的授權也提供額外費用$1,999美元的免版稅再分發保障。
  • 不中斷的產品支援:IronPDF提供持續的產品更新、安全功能升級,以及其工程團隊的支援,年費為$999美元或者一次性購價$1,999美元,可享受5年保障。

  • IronSuite:費用為$1,498美元,可獲得所有Iron Software產品的訪問權,包括IronPDF, IronOCR, IronWord, IronXL, IronBarcode, IronQR, IronZIP, IronPrint和IronWebScraper。

iText 授權

  • AGPL 授權: iText Core 函式庫是開源的,免費提供給用戶。在此授權模式下使用 iText,使用者必須遵守其條款,任何對 iText 的修改也必須依照 AGPL 授權模式發佈。
  • 商業授權: iText 提供商業授權模式,適用於不符合 AGPL 條款的開發專案,並採用報價定價模式。

文件和支援:IronPDF 與 iText

IronPDF

  • 全面的文件說明:涵蓋所有功能的廣泛且易於使用的文件說明。
  • 24/5 支援:提供積極的工程師支援。
  • 影片教程:YouTube 上提供逐步的影片指南。
  • 社區論壇:活躍的社區提供額外支援。

  • 定期更新:每月產品更新,確保最新功能和安全補丁。

iText

  • 文件: 涵蓋 iText 軟體所提供功能的深入文件。
  • 範例和教程: 提供使用其各種功能的教程以及程式碼範例。
  • GitHub: 開發者可以輕鬆將他們遇到的任何問題或錯誤提交到 iText 的 GitHub 資料庫,並與 iText 團隊進行溝通。
  • 更新: iText 提供定期的更新和改進。

有關 IronPDF 文件和支援的詳細信息,請訪問 IronPDF 文件檔案 和該 IronSoftware YouTube 頻道.

結論

在 .NET 的 PDF 操作工具領域中,IronPDF 和 iText 都提供了針對各種開發需求的強大功能。IronPDF 特別在於其在 .NET Core、Framework 和 Standard 等廣泛平台上的簡便集成,並且具有如 HTML 到 PDF 轉換和高級安全選項等全面功能。另一方面,以其 Java 背景著稱的 iText,提供了強大的 PDF 生成和操作工具,並同時提供開源和商業許可,強調了多樣性和定製化。

選擇這些工具最終取決於項目需求、許可偏好以及所需的技術支持水平。無論選擇簡單靈活的 IronPDF 還是功能豐富的開源 PDF 庫 iText,開發者都有足夠的資源在應用中有效地簡化 PDF 工作流程。

< 上一頁
IronPDF 與 Textcontrol 的比較
下一個 >
IronPDF和Winnovative PDF Library for .NET的比較

準備開始了嗎? 版本: 2024.9 剛剛發布

免費 NuGet 下載 總下載次數: 10,746,704 查看許可證 >