跳過到頁腳內容
產品比較

IronPDF與ITextPDF之比較

對於使用 PDF 的開發人員而言,擁有一個可靠的 PDF 產生與處理函式庫是非常重要的。 在 .NET 生態系統中,有兩個廣受歡迎的 PDF 函式庫脫穎而出 - IronPDFiTextPdf - 每個函式庫都提供強大的工具來建立、編輯和管理 PDF 文件。 本文將根據這些函式庫的功能能力、文件品質和定價政策,對這些函式庫進行深入的比較。

IronPDF 和 iTextPdf 的概述

IronPDF。

IronPDF 是用於 PDF 管理的強大 .NET 函式庫,相容於各種 .NET 環境 (Core 8、7、6、Framework 等)。 它提供了全面的功能集,包括 HTML 到 PDF 的轉換、合併 PDF、加密和數位簽章。 IronPDF 的說明文件簡單明瞭,使用者可以獲得可靠的技術支援。 開發人員通常會透過 Stack Overflow 討論和其他原始碼分享平台找到常見問題的解決方案。

iTextPdf

iTextPdf 是 iText 圖書館的 Java 和 .NET (C#) 的進階 PDF 圖書館,著重於企業級的文件處理。 本手冊同時提供 AGPL 與商業授權,為各種專案提供彈性。 iText 軟體(例如 iTextPdf)具有高度的客製化能力,使其成為複雜 PDF 任務(例如文件加密、數位簽署和表單建立)的理想選擇。

跨平台相容性

IronPDF 和 iTextPdf 均支援跨平台功能,使其能滿足 .NET 內各種應用程式的需求。 以下是每個函式庫的相容性細目。

IronPDF。

  • .NET版本:相容於 .NET Core (8、7、6、5、3.1+)、.NET Standard (2.0+) 及 .NET Framework (4.6.2+)。
  • 應用環境:可在 Windows、Linux、Mac、Docker、Azure 和 AWS 環境中無縫運作。
  • 支援的 IDE:與 Microsoft Visual Studio 和 JetBrains Rider & ReSharper 搭配使用。
  • 作業系統與處理器:支援 Windows、Mac、Linux、x64、x86、ARM。

iTextPdf

  • .NET版本:支援 .NET Core (2.x, 3.x)、.NET Framework (4.6.1+) 及 .NET 5+。
  • 應用環境:相容於 Windows、macOS、Linux 和 Docker。

主要功能比較:IronPDF vs. iTextPdf

以下是每個函式庫所提供的主要功能的詳細比較。

IronPDF。

  • HTML 至 PDF 轉檔:支援 HTML、CSS、JavaScript 及圖片。
  • PDF Manipulation:分割、合併和編輯 PDF 文件。
  • 安全性:PDF 加密和解密功能。
  • 編輯:允許註解、書籤和大綱。
  • 範本:套用頁眉、頁腳和頁碼。
  • 水印:支援使用 HTML/CSS 進行控制的文字和影像水印。
  • PDF 印章:在 PDF 檔案上新增圖片和文字戳記。

如需瞭解 IronPDF 所提供的廣泛功能的詳細資訊,請造訪 IronPDF功能頁面

iTextPdf

  • PDF 創建:支援從頭開始建立 PDF 文件。
  • 表格:提供 PDF 表單的建立與編輯。
  • 數位簽名:簽署 PDF 文件。
  • 壓縮:優化 PDF 檔案大小。
  • 內容萃取:從 PDF 中萃取文字和影像。
  • 自訂性:複雜專案的高度自訂性。

PDF 功能比較:IronPDF vs. iTextPdf

HTML 至 PDF 轉換

這兩個函式庫都支援 HTML 至 PDF 的轉換,但在方法和易用性上有所不同。

IronPDF

using IronPdf;

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

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

// Advanced example with external assets
var myAdvancedPdf = renderer.RenderHtmlAsPdf("<img src='icons/iron.png'>", @"C:\site\assets\");
myAdvancedPdf.SaveAs("html-with-assets.pdf");
using IronPdf;

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

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

// Advanced example with external assets
var myAdvancedPdf = renderer.RenderHtmlAsPdf("<img src='icons/iron.png'>", @"C:\site\assets\");
myAdvancedPdf.SaveAs("html-with-assets.pdf");
Imports IronPdf

' Instantiate the renderer
Private renderer = New ChromePdfRenderer()

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

' Advanced example with external assets
Dim myAdvancedPdf = renderer.RenderHtmlAsPdf("<img src='icons/iron.png'>", "C:\site\assets\")
myAdvancedPdf.SaveAs("html-with-assets.pdf")
$vbLabelText   $csharpLabel

iTextPdf

using iText.Html2pdf;
using System.IO;

public class HtmlToPdf
{
    public static void ConvertHtmlToPdf()
    {
        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;
using System.IO;

public class HtmlToPdf
{
    public static void ConvertHtmlToPdf()
    {
        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
Imports System.IO

Public Class HtmlToPdf
	Public Shared Sub ConvertHtmlToPdf()
		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
End Class
$vbLabelText   $csharpLabel

IronPDF 提供了直接的 HTML 至 PDF 轉換方法,包括對 HTML、CSS 和 JavaScript 的支援。 它允許使用者直接從 HTML 字串轉換,或包含具有可選基本路徑的資產。 iTextPdf 雖然有效,但需要較多的設定,更側重於以檔案為基礎的轉換。

加密 PDF 檔案

在安全性極為重要的情況下,加密是不可或缺的。 以下是每個圖書館的處理方式。

IronPDF

using IronPdf;

// Load an encrypted PDF or create a new one
var pdf = PdfDocument.FromFile("encrypted.pdf", "password");

// Set document security settings
pdf.SecuritySettings.MakePdfDocumentReadOnly("secret-key");
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.Password = "my-password";
pdf.SaveAs("secured.pdf");
using IronPdf;

// Load an encrypted PDF or create a new one
var pdf = PdfDocument.FromFile("encrypted.pdf", "password");

// Set document security settings
pdf.SecuritySettings.MakePdfDocumentReadOnly("secret-key");
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.Password = "my-password";
pdf.SaveAs("secured.pdf");
Imports IronPdf

' Load an encrypted PDF or create a new one
Private pdf = PdfDocument.FromFile("encrypted.pdf", "password")

' Set document security settings
pdf.SecuritySettings.MakePdfDocumentReadOnly("secret-key")
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.Password = "my-password"
pdf.SaveAs("secured.pdf")
$vbLabelText   $csharpLabel

iTextPdf

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

public class EncryptPdf
{
    public static readonly string DEST = "encrypt_pdf.pdf";
    public static readonly string OWNER_PASSWORD = "World";
    public static readonly string USER_PASSWORD = "Hello";

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

public class EncryptPdf
{
    public static readonly string DEST = "encrypt_pdf.pdf";
    public static readonly string OWNER_PASSWORD = "World";
    public static readonly string USER_PASSWORD = "Hello";

    protected void ManipulatePdf(string dest)
    {
        PdfDocument document = new PdfDocument(new PdfReader("input.pdf"), new PdfWriter(dest,
            new WriterProperties().SetStandardEncryption(
                Encoding.UTF8.GetBytes(USER_PASSWORD),
                Encoding.UTF8.GetBytes(OWNER_PASSWORD),
                EncryptionConstants.ALLOW_PRINTING,
                EncryptionConstants.ENCRYPTION_AES_128)));
        document.Close();
    }
}
Imports iText.Kernel.Pdf
Imports System.Text

Public Class EncryptPdf
	Public Shared ReadOnly DEST As String = "encrypt_pdf.pdf"
	Public Shared ReadOnly OWNER_PASSWORD As String = "World"
	Public Shared ReadOnly USER_PASSWORD As String = "Hello"

	Protected Sub ManipulatePdf(ByVal dest As String)
		Dim document As New PdfDocument(New PdfReader("input.pdf"), New PdfWriter(dest, (New WriterProperties()).SetStandardEncryption(Encoding.UTF8.GetBytes(USER_PASSWORD), Encoding.UTF8.GetBytes(OWNER_PASSWORD), EncryptionConstants.ALLOW_PRINTING, EncryptionConstants.ENCRYPTION_AES_128)))
		document.Close()
	End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF 的方法對使用者較為友善,提供直接的 加密和文件權限控制。 iTextPdf 雖然有效,但需要詳細設定,並注重加密標準。

重製 PDF 內容

對 PDF 檔案中的資訊進行隱藏處理對於隱私權和安全性而言至關重要。 以下是每個函式庫如何支援此功能。

IronPDF

using IronPdf;

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

// Redact 'are' from all pages
pdf.RedactTextOnAllPages("are");
pdf.SaveAs("redacted.pdf");
using IronPdf;

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

// Redact 'are' from all pages
pdf.RedactTextOnAllPages("are");
pdf.SaveAs("redacted.pdf");
Imports IronPdf

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

' Redact 'are' from all pages
pdf.RedactTextOnAllPages("are")
pdf.SaveAs("redacted.pdf")
$vbLabelText   $csharpLabel

iTextPdf

using iText.Kernel.Pdf;
using iText.Kernel.Colors;

// Define areas to redact on each page
Rectangle[] rectanglesToRedact = { new Rectangle(100, 100, 200, 50) };

// Draw black rectangles to cover sensitive areas
using (PdfDocument pdfDoc = new PdfDocument(new PdfReader("input.pdf"), new PdfWriter("output_redacted.pdf")))
{
    for (int pageNum = 1; pageNum <= pdfDoc.GetNumberOfPages(); pageNum++)
    {
        PdfPage page = pdfDoc.GetPage(pageNum);
        PdfCanvas canvas = new PdfCanvas(page);
        foreach (Rectangle rect in rectanglesToRedact)
        {
            canvas.SetFillColor(ColorConstants.BLACK)
                  .Rectangle(rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight())
                  .Fill();
        }
    }
}
using iText.Kernel.Pdf;
using iText.Kernel.Colors;

// Define areas to redact on each page
Rectangle[] rectanglesToRedact = { new Rectangle(100, 100, 200, 50) };

// Draw black rectangles to cover sensitive areas
using (PdfDocument pdfDoc = new PdfDocument(new PdfReader("input.pdf"), new PdfWriter("output_redacted.pdf")))
{
    for (int pageNum = 1; pageNum <= pdfDoc.GetNumberOfPages(); pageNum++)
    {
        PdfPage page = pdfDoc.GetPage(pageNum);
        PdfCanvas canvas = new PdfCanvas(page);
        foreach (Rectangle rect in rectanglesToRedact)
        {
            canvas.SetFillColor(ColorConstants.BLACK)
                  .Rectangle(rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight())
                  .Fill();
        }
    }
}
Imports iText.Kernel.Pdf
Imports iText.Kernel.Colors

' Define areas to redact on each page
Private rectanglesToRedact() As Rectangle = { New Rectangle(100, 100, 200, 50) }

' Draw black rectangles to cover sensitive areas
Using pdfDoc As New PdfDocument(New PdfReader("input.pdf"), New PdfWriter("output_redacted.pdf"))
	Dim pageNum As Integer = 1
	Do While pageNum <= pdfDoc.GetNumberOfPages()
		Dim page As PdfPage = pdfDoc.GetPage(pageNum)
		Dim canvas As New PdfCanvas(page)
		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
$vbLabelText   $csharpLabel

IronPdf 提供方便的 刪除工具,可輕鬆隱藏所有頁面中的敏感文字。 相較之下,iTextPdf 則需要使用者手動定義並套用黑色矩形以覆蓋敏感區域。

簽署 PDF 文件

自動簽署 PDF 文件可以大幅節省時間。以下是 IronPDF 和 iTextPdf 處理數位簽章的並列比較。

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

iTextPdf

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

當提到要將 數位簽章套用至 PDF 檔案時,IronPDF 提供了直接有效的方式,利用 X509 憑證來完成這項工作。 其 API 簡化了流程,使其容易整合到工作流程中,而不會犧牲對簽章安全性的控制。 相較之下,iTextPDF 簽署文件的流程設定較為複雜,但提供額外的客製化選項。 開發人員擁有更細緻的控制權,儘管他們在瀏覽 iTextPDF 的簽章設定和憑證處理時,可能會面臨較陡峭的學習曲線。

將水印套用至 PDF 文件

PDF 的水印對於品牌、機密性和版權保護來說是不可或缺的。 以下是 IronPDF 和 iTextPDF 如何將水印套用至 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")
$vbLabelText   $csharpLabel

iTextPdf

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();

        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();

        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()

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

IronPDF 的 API 可實現快速直觀的 水印應用程式,並可靈活使用 HTML 和 CSS 進行客製化。 另一方面,iTextPDF 可透過其更詳細的設定選項高度自訂水印位置,不過需要更大量的編碼工作。

在 PDF 上標示圖片和文字

在 PDF 上燙印內容與套用水印類似,但更著重於加入特定元素,例如圖片或文字,以達到標籤或品牌的目的。 以下是 IronPdf 和 iTextPDF 如何執行這項任務。

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

iTextPdf

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

IronPdf 的 圖像和文字戳記方法簡化且功能多樣,讓開發人員可以輕鬆地在 PDF 頁面上新增品牌內容或標籤。 API 利用熟悉的 HTML/CSS 造型元素,讓客製化變得簡單直接。 iTextPDF 也提供圖片和文字戳記功能,不過其設定需要較多的手動設定和 PDF 排版結構的工作知識。 直接在 PDF 頁面上處理和樣式化內容的能力,為開發人員提供了強大的戳記工具,不過 iTextPDF 的設定可能需要多花一點心思。

將 DOCX 轉換為 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")
$vbLabelText   $csharpLabel

iTextPDF

與 IronPDF 不同,iTextPDF 沒有內建將 DOCX 轉換為 PDF 的支援。 若要執行此轉換,開發人員必須仰賴 DocX 或 Aspose.Words 等第三方函式庫,先將 DOCX 檔案轉換為 PDF 相容格式,然後再使用 iTextPDF 進行處理或修改。

IronPDF 為 DOCX 到 PDF 的轉換提供了直接、內建的解決方案,不需要額外的函式庫。 這使得它非常適合需要快速整合方法的開發人員。 相較之下,iTextPDF 依賴外部函式庫來轉換 DOCX 檔案,需要額外的設定和依賴,這可能會增加專案的複雜性。

Bootstrap 與現代 CSS 架構支援。

從 Bootstrap 風格的 Web 應用程式產生 PDF 時,完整的框架支援可確保設計的一致性,而不需要平行的 CSS 檔案或版面修改。

IronPDF。:完整的 Bootstrap 框架支援。

IronPDF 的 Chromium 引擎提供完整的支援:

  • Bootstrap 5:完整的 flexbox 布局、CSS Grid、實用類型、所有元件
  • Bootstrap 4:完整的卡片系統、導航、flex 公用程式、反應式設計
  • Tailwind CSS:具有瀏覽器精確呈現的所有實用類別
  • 基礎:完整的網格系統和元件庫
  • 現代 CSS3:Flexbox、CSS Grid、自訂屬性、動畫、轉場

真實世界驗證:IronPDF 以像素級的精確度渲染 Bootstrap 首頁和所有 官方範例

iTextPDF:有限的 Bootstrap 支援

iTextPDF 使用具有選擇性 CSS3 支援的 pdfHTML:

  • 有限的 flexbox 支援:在 7.1.15 版中新增,但不完整
  • No CSS Grid:不支援基於網格的 Bootstrap 佈局
  • Bootstrap 3 的限制:現代 Bootstrap 4/5 元件需要解決方案
  • 手動版面轉換:複雜的版面通常需要 PDF 特定的程式碼

iTextPDF 的說明文件明確指出,進階的 CSS 功能可能無法如預期般呈現,因此開發人員必須測試每個 Bootstrap 元件,並經常建立簡化的版面。

開發影響:團隊必須維護用於生成 PDF 的單獨佈局代碼,或者廣泛測試和修改 Bootstrap 元件,從而增加開發時間並減少設計一致性。

如需全面的 Bootstrap 框架指南和 CSS3 渲染功能,請參閱 Bootstrap & Flexbox CSS 指南

程式碼範例比較摘要

IronPdf vs iTextPDF 對比圖

如需更詳細的範例,請造訪 IronPDF範例

定價與授權:IronPDF vs. iTextPdf Library

IronPDF。 定價與授權

IronPDF 有不同等級和購買授權的附加功能。 開發人員也可以購買 Iron Suite,以兩件產品的價格即可使用 IronSoftware 的所有產品。 如果您尚未準備好購買授權,IronPDF 提供 免費試用

  • 永久授權:根據您的團隊規模、專案需求和地點數量,提供一系列永久授權。 每種授權類型都附有電子郵件支援。
  • Lite License:此授權費用為 $799 並支援一位開發人員、一個地點和一個專案。
  • Plus License: 支援三位開發人員、三個地點和三個專案,這是 Lite License 的進階版本,費用為 $1,199。 Plus License 除了提供基本的電子郵件支援外,還提供聊天支援和電話支援。
  • Professional License:此 License 適合較大規模的團隊,可支援十位開發人員、十個地點和十個專案,費用為 $2,399 。 它提供與前幾層相同的聯絡支援管道,但也提供螢幕分享支援。
  • 免版稅再發行: IronPDF 的授權也提供免版稅再發行的保障,只需額外支付 $2,399 即可。
  • 不間斷的產品支援: IronPdf 提供持續的產品更新、安全功能升級,以及工程團隊的支援,費用為 999 美元/年或一次性購買 5 年保障的 1,999 美元。
  • Iron Suite:只需 $1,498 即可使用所有 Iron Software 產品,包括 IronPDF、IronOCR、IronWord、IronXL、IronBarcode、IronQR、IronZIP、IronPrint 和 IronWebScraper。

IronPDF vs iTextPDF 定價圖片

iTextPDF 授權

  • AGPL 授權條款:iTextPDF Core 函式庫以 AGPL 授權條款開放原始碼,在符合條件下可自由使用。 開發人員必須以相同的授權釋出任何修改。
  • 商業授權:對於不符合 AGPL 條件的開發人員,iTextPDF 透過引用模式提供商業授權。

文件和支援:IronPDF vs. iTextPdf

IronPDF。

  • 全面的說明文件: 涵蓋其所有功能的廣泛且友善的說明文件。
  • 24/5 支援:提供積極的工程師支援。
  • 視訊教學:YouTube 上提供了分步視訊指南。
  • 社群論壇:提供額外支援的參與社群。
  • 定期更新:每月進行產品更新,以確保提供最新的功能和安全修補程式。

iTextPDF

iTextPDF 為其廣泛的功能集提供強大的文件和支援。

  • 說明文件:iText PDF 說明文件徹底涵蓋可用的功能。
  • 範例與教學:程式碼範例和教學可幫助開發人員入門。
  • GitHub 社群:開發人員可以報告問題、提交拉取請求,並與 iTextPDF 團隊互動。
  • 定期更新:iTextPDF 提供頻繁的更新和改進。

有關 IronPDF 文件和支援的詳細資訊,請造訪 IronPDF 文件IronSoftware YouTube 頻道

結論

在 .NET 的 PDF 操作工具領域中,IronPDF 和 iTextPDF 都為開發人員提供了強大的解決方案。 IronPDF for .NET 以其跨 .NET 平台的簡單整合和人性化功能脫穎而出,例如 DOCX 到 PDF 的轉換,無需外部依賴。 相比之下,iTextPDF 以其多功能性和豐富的功能集著稱,仍然是一個功能強大的選擇,尤其是與其他工具搭配使用時,儘管它需要額外的依賴才能進行 DOCX 轉換。

最終,在 IronPDF 和 iTextPDF 之間做選擇,將取決於您專案的特定需求、授權偏好,以及所需的支援層級。 這兩個函式庫都提供了可靠的方式來簡化 .NET 應用程式中的 PDF 工作流程。

請注意iTextPDF 是其各自擁有者的註冊商標。 本網站與 iTextPDF 無任何關聯、背書或贊助。 所有產品名稱、標誌和品牌均為其各自擁有者的財產。 比較資料僅供參考,並反映撰寫時的公開資訊。

常見問題解答

如何在 C# 中將 HTML 轉換為 PDF?

您可以使用 IronPDF 的 RenderHtmlAsPdf 方法將 HTML 字串轉換成 PDF。您也可以使用 RenderHtmlFileAsPdf 將 HTML 檔案轉換成 PDF。

IronPDF 在 PDF 創建和處理方面提供哪些功能?

IronPDF 提供 HTML 至 PDF 轉換、PDF 合併、加密、數位簽名、水印以及 DOCX 至 PDF 轉換等功能。

IronPDF 如何簡化 PDF 簽署?

IronPDF 允許您使用 X509 憑證對 PDF 檔案套用數位簽章,提供一種直接的方法來保護您的文件。

IronPDF 可以在不同的作業系統上使用嗎?

是的,IronPDF 支持跨平台兼容性。它可以在 Windows、Linux 和 Mac 上無縫運作,並與 .NET Core、.NET Standard 和 .NET Framework 相容。

在文件加密方面,iTextPDF 與 IronPDF 有何不同?

iTextPDF 提供加密標準的詳細設定,而 IronPDF 則透過容易實作的內建加密方法簡化流程。

IronPDF 用戶可獲得哪些支援資源?

IronPDF 透過全面的文件、視訊教學、社群論壇和 24/5 工程師支援,提供廣泛的支援。

IronPDF 如何處理 DOCX 至 PDF 的轉換?

IronPDF 包含 DOCX 至 PDF 的原生轉換功能,可無縫整合而不需要額外的函式庫。

IronPDF 有哪些授權選項?

IronPDF 提供 Lite、Plus、Professional 等不同層級的永久 License,以及免權利金再授權和持續產品支援的選項。

如何使用 IronPDF 為 PDF 套用水印?

IronPDF 可讓您使用 HTML 和 CSS 輕鬆套用水印,使您能夠快速新增文字或圖片水印,並根據需要自訂水印。

IronPDF 為什麼適合使用 .NET 應用程式的開發人員?

IronPDF 採用簡化的 API 設計,對使用者友善,使其能有效率地執行 HTML 轉換為 PDF、加密和數位簽章等任務,非常適合 .NET 開發人員使用。

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。

iText Logo

厭倦了昂貴的續費和過時的產品更新嗎?

iText 輕鬆轉換為我們的工程遷移支援和更優惠的價格。

IronPDF Logo