跳過到頁腳內容
遷移指南

如何用 C# 從 Api2pdf 轉移到 IronPDF

Api2pdf 提供基於雲端的 PDF 生成服務,但將敏感文件傳送到外部伺服器可能會導致安全風險、合規性問題以及持續的成本,這些成本會隨著時間的推移而累積。本指南詳細介紹了從Api2pdf遷移到IronPDF的路徑。IronPDF是一個原生 .NET PDF 庫,它完全在您自己的基礎設施上處理文檔,消除了資料傳輸方面的顧慮,並將每次轉換的成本轉化為一次性投資。

為什麼考慮從 API2PDF 遷移?

雖然Api2pdf提供了便利的基於雲端的 PDF 生成功能,但多種因素促使開發團隊尋求本地部署的替代方案來滿足其 PDF 生成需求。

安全和合規問題

Api2pdf 以雲端服務的方式運作,您的敏感 HTML 和文件會傳送到第三方伺服器進行處理。 這對於處理受監管資料的組織造成了重大的疑慮。

風險 Api2pdf IronPDF
資料傳輸 所有發送至外部伺服器的內容 在您的基礎架構上進行本機處理
符合 GDPR 規範 資料跨越司法管轄區 資料永不離開您的環境
HIPAA 合規性 從外部傳輸的 PHI PHI 保留在您的系統中
SOC 2 第三方依賴 完全控制資料處理
PCI DSS 可能暴露的卡片資料 無外部傳輸

隨時間累積的成本

Api2pdf 無限期收取每次轉換約 0.005 美元的費用,而IronPDF則提供一次性永久授權。 對於產生大量 PDF 的應用程式而言,成本差異會變得相當大:

工作量 Api2pdf (年度) IronPDF (一次性)
每月 10,000 份 PDF ~$600/年 $749 (Lite)
每月 50,000 份 PDF ~$3,000/year $749 (Lite)
每月 100,000 份 PDF ~$6,000/year 1,499 美元 (Plus)

對於大多數生產應用程式而言,IronPDF 可在幾個月內收回成本。

效能與可用性

Api2pdf 需要網路迴圈,每次產生 PDF 請求會增加 2-5 秒的延遲。IronPDF 在本地處理的時間為 100-500 毫秒。 此外,IronPDF 可在完全離線和空氣封閉的環境中運作 - 這對於無法依賴外部服務可用性的應用程式來說非常重要。

Api2pdfvs. IronPDF:主要差異

範疇 Api2pdf IronPDF
資料處理 傳送至第三方雲端伺服器 在您的基礎架構上進行本地處理
定價 每次轉換付費 (~$0.005/PDF) 一次性永久授權
交稿時間 2-5 秒 (網路往返) 100-500 毫秒(本地處理)
離線 無法提供 完全離線工作
安裝 API 金鑰 + HTTP 客戶端 簡單的 NuGet 套件
合規性 GDPR/HIPAA 關注 (資料離開網路) 完全符合規定的控制

逐步遷移的過程

步驟 1:更新 NuGet 套件

移除Api2pdf套件並安裝 IronPDF:

# Remove Api2pdf
dotnet remove package Api2Pdf

# Install IronPDF
dotnet add package IronPdf
# Remove Api2pdf
dotnet remove package Api2Pdf

# Install IronPDF
dotnet add package IronPdf
SHELL

或透過套件管理員控制台:

Uninstall-Package Api2Pdf
Install-Package IronPdf

步驟 2:更新命名空間參考資料

用IronPDF取代Api2pdf命名空間:

// Remove these
using Api2Pdf;
using Api2Pdf.DotNet;

// Add these
using IronPdf;
using IronPdf.Rendering;
// Remove these
using Api2Pdf;
using Api2Pdf.DotNet;

// Add these
using IronPdf;
using IronPdf.Rendering;
Imports IronPdf
Imports IronPdf.Rendering
$vbLabelText   $csharpLabel

步驟 3:配置授權金鑰

在應用程式啟動時設定IronPDF授權金鑰:

// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";

// Or configure via appsettings.json:
// { "IronPdf.LicenseKey": "YOUR-IRONPDF-LICENSE-KEY" }
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";

// Or configure via appsettings.json:
// { "IronPdf.LicenseKey": "YOUR-IRONPDF-LICENSE-KEY" }
' Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY"

' Or configure via appsettings.json:
' { "IronPdf.LicenseKey": "YOUR-IRONPDF-LICENSE-KEY" }
$vbLabelText   $csharpLabel

步驟 4:移除 API 金鑰組態

IronPDF 可在本機執行,不需要 API 金鑰:

// Remove thisApi2pdfpattern
var client = new Api2PdfClient("API_KEY");

// Just create the renderer directly
var renderer = new ChromePdfRenderer();
// Remove thisApi2pdfpattern
var client = new Api2PdfClient("API_KEY");

// Just create the renderer directly
var renderer = new ChromePdfRenderer();
' Remove thisApi2pdfpattern
Dim client = New Api2PdfClient("API_KEY")

' Just create the renderer directly
Dim renderer = New ChromePdfRenderer()
$vbLabelText   $csharpLabel

完整的 API 遷移參考。

核心類映射

Api2pdf 類別 IronPDF 同等級產品
Api2PdfClient ChromePdfRenderer
Api2PdfResult PdfDocument
HeadlessChromeOptions ChromePdfRenderOptions

方法映射

Api2pdf 方法 IronPDF 方法
client.HeadlessChrome.FromHtmlAsync(html) renderer.RenderHtmlAsPdf(html)
client.HeadlessChrome.FromUrlAsync(url) renderer.RenderUrlAsPdf(url)
response.Pdf (URL) pdf.SaveAs(path)
response.Pdf(下載) pdf.BinaryData
client.PdfSharp.MergePdfsAsync(urls) PdfDocument.Merge(pdfs)
client.PdfSharp.SetPasswordAsync(url, pwd) pdf.SecuritySettings.OwnerPassword

渲染選項對應

Api2pdf 選項 IronPDF 選項
Landscape = true RenderingOptions.PaperOrientation = Landscape
PageSize = "A4" RenderingOptions.PaperSize = PdfPaperSize.A4
PrintBackground = true RenderingOptions.PrintHtmlBackgrounds = true
MarginTop,等等。 RenderingOptions.MarginTop,等等。
Delay = 5000 RenderingOptions.WaitFor.RenderDelay(5000)

程式碼遷移範例

HTML 至 PDF 轉換

最常見的Api2pdf操作反映了根本性的轉變——從雲端 API 呼叫到本地處理。

Api2pdf 實作:

// NuGet: Install-Package Api2Pdf.DotNet
using System;
using System.Threading.Tasks;
using Api2Pdf.DotNet;

class Program
{
    static async Task Main(string[] args)
    {
        var a2pClient = new Api2PdfClient("your-api-key");
        var apiResponse = await a2pClient.HeadlessChrome.FromHtmlAsync("<h1>Hello World</h1>");
        Console.WriteLine(apiResponse.Pdf);
    }
}
// NuGet: Install-Package Api2Pdf.DotNet
using System;
using System.Threading.Tasks;
using Api2Pdf.DotNet;

class Program
{
    static async Task Main(string[] args)
    {
        var a2pClient = new Api2PdfClient("your-api-key");
        var apiResponse = await a2pClient.HeadlessChrome.FromHtmlAsync("<h1>Hello World</h1>");
        Console.WriteLine(apiResponse.Pdf);
    }
}
Imports System
Imports System.Threading.Tasks
Imports Api2Pdf.DotNet

Module Program
    Async Function Main(args As String()) As Task
        Dim a2pClient = New Api2PdfClient("your-api-key")
        Dim apiResponse = Await a2pClient.HeadlessChrome.FromHtmlAsync("<h1>Hello World</h1>")
        Console.WriteLine(apiResponse.Pdf)
    End Function
End Module
$vbLabelText   $csharpLabel

IronPDF 實作:

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
Imports System
Imports IronPdf

Class Program
    Shared Sub Main(ByVal args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>")
        pdf.SaveAs("output.pdf")
        Console.WriteLine("PDF created successfully")
    End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF 省去了網路往返、API 金鑰管理,以及Api2pdf基於 URL 的回應模式所需的獨立下載步驟。

URL 轉 PDF

Api2pdf 實作:

// NuGet: Install-Package Api2Pdf.DotNet
using System;
using System.Threading.Tasks;
using Api2Pdf.DotNet;

class Program
{
    static async Task Main(string[] args)
    {
        var a2pClient = new Api2PdfClient("your-api-key");
        var apiResponse = await a2pClient.HeadlessChrome.FromUrlAsync("https://www.example.com");
        Console.WriteLine(apiResponse.Pdf);
    }
}
// NuGet: Install-Package Api2Pdf.DotNet
using System;
using System.Threading.Tasks;
using Api2Pdf.DotNet;

class Program
{
    static async Task Main(string[] args)
    {
        var a2pClient = new Api2PdfClient("your-api-key");
        var apiResponse = await a2pClient.HeadlessChrome.FromUrlAsync("https://www.example.com");
        Console.WriteLine(apiResponse.Pdf);
    }
}
Imports System
Imports System.Threading.Tasks
Imports Api2Pdf.DotNet

Module Program
    Async Function Main(args As String()) As Task
        Dim a2pClient = New Api2PdfClient("your-api-key")
        Dim apiResponse = Await a2pClient.HeadlessChrome.FromUrlAsync("https://www.example.com")
        Console.WriteLine(apiResponse.Pdf)
    End Function
End Module
$vbLabelText   $csharpLabel

IronPDF 實作:

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("PDF created from URL successfully");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("PDF created from URL successfully");
    }
}
Imports System
Imports IronPdf

Module Program
    Sub Main(args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
        pdf.SaveAs("webpage.pdf")
        Console.WriteLine("PDF created from URL successfully")
    End Sub
End Module
$vbLabelText   $csharpLabel

將 HTML 檔案轉換為 PDF 的選項

Api2pdf 實作:

// NuGet: Install-Package Api2Pdf.DotNet
using System;
using System.IO;
using System.Threading.Tasks;
using Api2Pdf.DotNet;

class Program
{
    static async Task Main(string[] args)
    {
        var a2pClient = new Api2PdfClient("your-api-key");
        string html = File.ReadAllText("input.html");
        var options = new HeadlessChromeOptions
        {
            Landscape = true,
            PrintBackground = true
        };
        var apiResponse = await a2pClient.HeadlessChrome.FromHtmlAsync(html, options);
        Console.WriteLine(apiResponse.Pdf);
    }
}
// NuGet: Install-Package Api2Pdf.DotNet
using System;
using System.IO;
using System.Threading.Tasks;
using Api2Pdf.DotNet;

class Program
{
    static async Task Main(string[] args)
    {
        var a2pClient = new Api2PdfClient("your-api-key");
        string html = File.ReadAllText("input.html");
        var options = new HeadlessChromeOptions
        {
            Landscape = true,
            PrintBackground = true
        };
        var apiResponse = await a2pClient.HeadlessChrome.FromHtmlAsync(html, options);
        Console.WriteLine(apiResponse.Pdf);
    }
}
no response after 91 seconds
$vbLabelText   $csharpLabel

IronPDF 實作:

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

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
        string html = File.ReadAllText("input.html");
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created with options successfully");
    }
}
// NuGet: Install-Package IronPdf
using System;
using System.IO;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
        string html = File.ReadAllText("input.html");
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created with options successfully");
    }
}
Imports System
Imports System.IO
Imports IronPdf

Module Program
    Sub Main(args As String())
        Dim renderer As New ChromePdfRenderer()
        renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Landscape
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print
        Dim html As String = File.ReadAllText("input.html")
        Dim pdf = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs("output.pdf")
        Console.WriteLine("PDF created with options successfully")
    End Sub
End Module
$vbLabelText   $csharpLabel

IronPDF 可直接在渲染器物件上設定渲染選項,而非將其作為單獨的選項參數傳送給每個 API 呼叫。

合併多個 PDF 文件

Api2pdf 實作:

using Api2Pdf.DotNet;

var a2pClient = new Api2PdfClient("YOUR_API_KEY");

var pdfUrls = new List<string>
{
    "https://example.com/pdf1.pdf",
    "https://example.com/pdf2.pdf",
    "https://example.com/pdf3.pdf"
};

var request = new PdfMergeRequest { Urls = pdfUrls };
var response = await a2pClient.PdfSharp.MergePdfsAsync(request);

if (response.Success)
{
    // Download merged PDF from response.Pdf URL
}
using Api2Pdf.DotNet;

var a2pClient = new Api2PdfClient("YOUR_API_KEY");

var pdfUrls = new List<string>
{
    "https://example.com/pdf1.pdf",
    "https://example.com/pdf2.pdf",
    "https://example.com/pdf3.pdf"
};

var request = new PdfMergeRequest { Urls = pdfUrls };
var response = await a2pClient.PdfSharp.MergePdfsAsync(request);

if (response.Success)
{
    // Download merged PDF from response.Pdf URL
}
Imports Api2Pdf.DotNet

Dim a2pClient = New Api2PdfClient("YOUR_API_KEY")

Dim pdfUrls = New List(Of String) From {
    "https://example.com/pdf1.pdf",
    "https://example.com/pdf2.pdf",
    "https://example.com/pdf3.pdf"
}

Dim request = New PdfMergeRequest With {.Urls = pdfUrls}
Dim response = Await a2pClient.PdfSharp.MergePdfsAsync(request)

If response.Success Then
    ' Download merged PDF from response.Pdf URL
End If
$vbLabelText   $csharpLabel

IronPDF 實作:

using IronPdf;

// Load PDFs from files
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var pdf3 = PdfDocument.FromFile("document3.pdf");

// Merge all PDFs
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("merged.pdf");
using IronPdf;

// Load PDFs from files
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var pdf3 = PdfDocument.FromFile("document3.pdf");

// Merge all PDFs
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("merged.pdf");
Imports IronPdf

' Load PDFs from files
Dim pdf1 = PdfDocument.FromFile("document1.pdf")
Dim pdf2 = PdfDocument.FromFile("document2.pdf")
Dim pdf3 = PdfDocument.FromFile("document3.pdf")

' Merge all PDFs
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("merged.pdf")
$vbLabelText   $csharpLabel

IronPDF 的靜態 Merge 方法直接接受多個文檔,從而消除了基於 URL 的工作流程。

受密碼保護的 PDF 文件

Api2pdf 實作:

using Api2Pdf.DotNet;

var a2pClient = new Api2PdfClient("YOUR_API_KEY");

// Generate PDF first
var pdfResponse = await a2pClient.HeadlessChrome.FromHtmlAsync("<h1>Confidential</h1>");

// Then add password protection in separate call
var protectedResponse = await a2pClient.PdfSharp.SetPasswordAsync(
    pdfResponse.Pdf,
    "secretpassword"
);
using Api2Pdf.DotNet;

var a2pClient = new Api2PdfClient("YOUR_API_KEY");

// Generate PDF first
var pdfResponse = await a2pClient.HeadlessChrome.FromHtmlAsync("<h1>Confidential</h1>");

// Then add password protection in separate call
var protectedResponse = await a2pClient.PdfSharp.SetPasswordAsync(
    pdfResponse.Pdf,
    "secretpassword"
);
Imports Api2Pdf.DotNet

Dim a2pClient = New Api2PdfClient("YOUR_API_KEY")

' Generate PDF first
Dim pdfResponse = Await a2pClient.HeadlessChrome.FromHtmlAsync("<h1>Confidential</h1>")

' Then add password protection in separate call
Dim protectedResponse = Await a2pClient.PdfSharp.SetPasswordAsync(pdfResponse.Pdf, "secretpassword")
$vbLabelText   $csharpLabel

IronPDF 實作:

using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");

// Set security in one step
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

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

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");

// Set security in one step
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

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

Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>")

' Set security in one step
pdf.SecuritySettings.OwnerPassword = "owner123"
pdf.SecuritySettings.UserPassword = "user123"
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit

pdf.SaveAs("protected.pdf")
$vbLabelText   $csharpLabel

IronPDF 透過 SecuritySettings 屬性提供 PDF 權限的精細控制。

頁首和頁尾

Api2pdf 實作:

using Api2Pdf.DotNet;

var a2pClient = new Api2PdfClient("YOUR_API_KEY");

var options = new HeadlessChromeOptions
{
    HeaderHtml = "<div style='font-size:10px'>Company Header</div>",
    FooterHtml = "<div style='font-size:10px'>Page <span class='pageNumber'></span></div>"
};

var response = await a2pClient.HeadlessChrome.FromHtmlAsync(html, options);
using Api2Pdf.DotNet;

var a2pClient = new Api2PdfClient("YOUR_API_KEY");

var options = new HeadlessChromeOptions
{
    HeaderHtml = "<div style='font-size:10px'>Company Header</div>",
    FooterHtml = "<div style='font-size:10px'>Page <span class='pageNumber'></span></div>"
};

var response = await a2pClient.HeadlessChrome.FromHtmlAsync(html, options);
Imports Api2Pdf.DotNet

Dim a2pClient = New Api2PdfClient("YOUR_API_KEY")

Dim options = New HeadlessChromeOptions With {
    .HeaderHtml = "<div style='font-size:10px'>Company Header</div>",
    .FooterHtml = "<div style='font-size:10px'>Page <span class='pageNumber'></span></div>"
}

Dim response = Await a2pClient.HeadlessChrome.FromHtmlAsync(html, options)
$vbLabelText   $csharpLabel

IronPDF 實作:

using IronPdf;

var renderer = new ChromePdfRenderer();

// HTML headers and footers with full styling
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Company Header</div>",
    DrawDividerLine = true
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("with-headers.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();

// HTML headers and footers with full styling
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Company Header</div>",
    DrawDividerLine = true
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("with-headers.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()

' HTML headers and footers with full styling
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='font-size:10px; text-align:center;'>Company Header</div>",
    .DrawDividerLine = True
}

renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='font-size:10px; text-align:center;'>Page {page} of {total-pages}</div>",
    .DrawDividerLine = True
}

Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("with-headers.pdf")
$vbLabelText   $csharpLabel

IronPDF 支援像 {page}{total-pages} 這樣的佔位標記,用於動態頁碼。 如需更多選項,請參閱 headers and footers 文件

ASP.NET Core 整合。

Api2pdf 的 async HTTP 模式與IronPDF的直接 PDF 生成有很大的不同。

Api2pdf模式:

[ApiController]
public class PdfController : ControllerBase
{
    private readonly Api2PdfClient _client;

    public PdfController()
    {
        _client = new Api2PdfClient("YOUR_API_KEY");
    }

    [HttpGet("generate")]
    public async Task<IActionResult> GeneratePdf()
    {
        var response = await _client.HeadlessChrome.FromHtmlAsync("<h1>Report</h1>");

        if (!response.Success)
            return BadRequest(response.Error);

        // Redirect to download URL
        return Redirect(response.Pdf);
    }
}
[ApiController]
public class PdfController : ControllerBase
{
    private readonly Api2PdfClient _client;

    public PdfController()
    {
        _client = new Api2PdfClient("YOUR_API_KEY");
    }

    [HttpGet("generate")]
    public async Task<IActionResult> GeneratePdf()
    {
        var response = await _client.HeadlessChrome.FromHtmlAsync("<h1>Report</h1>");

        if (!response.Success)
            return BadRequest(response.Error);

        // Redirect to download URL
        return Redirect(response.Pdf);
    }
}
Imports Microsoft.AspNetCore.Mvc

<ApiController>
Public Class PdfController
    Inherits ControllerBase

    Private ReadOnly _client As Api2PdfClient

    Public Sub New()
        _client = New Api2PdfClient("YOUR_API_KEY")
    End Sub

    <HttpGet("generate")>
    Public Async Function GeneratePdf() As Task(Of IActionResult)
        Dim response = Await _client.HeadlessChrome.FromHtmlAsync("<h1>Report</h1>")

        If Not response.Success Then
            Return BadRequest(response.Error)
        End If

        ' Redirect to download URL
        Return Redirect(response.Pdf)
    End Function
End Class
$vbLabelText   $csharpLabel

IronPDF模式:

[ApiController]
public class PdfController : ControllerBase
{
    [HttpGet("generate")]
    public IActionResult GeneratePdf()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");

        // Return PDF directly - no download step needed
        return File(pdf.BinaryData, "application/pdf", "report.pdf");
    }

    [HttpGet("generate-async")]
    public async Task<IActionResult> GeneratePdfAsync()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>");

        return File(pdf.Stream, "application/pdf", "report.pdf");
    }
}
[ApiController]
public class PdfController : ControllerBase
{
    [HttpGet("generate")]
    public IActionResult GeneratePdf()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");

        // Return PDF directly - no download step needed
        return File(pdf.BinaryData, "application/pdf", "report.pdf");
    }

    [HttpGet("generate-async")]
    public async Task<IActionResult> GeneratePdfAsync()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>");

        return File(pdf.Stream, "application/pdf", "report.pdf");
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports System.Threading.Tasks

<ApiController>
Public Class PdfController
    Inherits ControllerBase

    <HttpGet("generate")>
    Public Function GeneratePdf() As IActionResult
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>")

        ' Return PDF directly - no download step needed
        Return File(pdf.BinaryData, "application/pdf", "report.pdf")
    End Function

    <HttpGet("generate-async")>
    Public Async Function GeneratePdfAsync() As Task(Of IActionResult)
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = Await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>")

        Return File(pdf.Stream, "application/pdf", "report.pdf")
    End Function
End Class
$vbLabelText   $csharpLabel

IronPDF 直接透過 BinaryDataStream 返回 PDF,從而消除了重定向到下載模式。

依賴注入配置

// Program.cs or Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IPdfService, IronPdfService>();
}

// IPdfService.cs
public interface IPdfService
{
    PdfDocument GenerateFromHtml(string html);
    Task<PdfDocument> GenerateFromHtmlAsync(string html);
}

// IronPdfService.cs
public class IronPdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;

    public IronPdfService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
    }

    public PdfDocument GenerateFromHtml(string html) =>
        _renderer.RenderHtmlAsPdf(html);

    public Task<PdfDocument> GenerateFromHtmlAsync(string html) =>
        _renderer.RenderHtmlAsPdfAsync(html);
}
// Program.cs or Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IPdfService, IronPdfService>();
}

// IPdfService.cs
public interface IPdfService
{
    PdfDocument GenerateFromHtml(string html);
    Task<PdfDocument> GenerateFromHtmlAsync(string html);
}

// IronPdfService.cs
public class IronPdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;

    public IronPdfService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
    }

    public PdfDocument GenerateFromHtml(string html) =>
        _renderer.RenderHtmlAsPdf(html);

    public Task<PdfDocument> GenerateFromHtmlAsync(string html) =>
        _renderer.RenderHtmlAsPdfAsync(html);
}
' Program.vb or Startup.vb
Public Sub ConfigureServices(services As IServiceCollection)
    services.AddScoped(Of IPdfService, IronPdfService)()
End Sub

' IPdfService.vb
Public Interface IPdfService
    Function GenerateFromHtml(html As String) As PdfDocument
    Function GenerateFromHtmlAsync(html As String) As Task(Of PdfDocument)
End Interface

' IronPdfService.vb
Public Class IronPdfService
    Implements IPdfService

    Private ReadOnly _renderer As ChromePdfRenderer

    Public Sub New()
        _renderer = New ChromePdfRenderer()
        _renderer.RenderingOptions.PrintHtmlBackgrounds = True
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
    End Sub

    Public Function GenerateFromHtml(html As String) As PdfDocument Implements IPdfService.GenerateFromHtml
        Return _renderer.RenderHtmlAsPdf(html)
    End Function

    Public Function GenerateFromHtmlAsync(html As String) As Task(Of PdfDocument) Implements IPdfService.GenerateFromHtmlAsync
        Return _renderer.RenderHtmlAsPdfAsync(html)
    End Function
End Class
$vbLabelText   $csharpLabel

錯誤處理轉換

Api2pdf 使用回應物件檢查。IronPDF使用標準的 .NET 例外。

Api2pdf模式:

var response = await a2pClient.HeadlessChrome.FromHtmlAsync(html);

if (!response.Success)
{
    Console.WriteLine($"Error: {response.Error}");
    return;
}
var response = await a2pClient.HeadlessChrome.FromHtmlAsync(html);

if (!response.Success)
{
    Console.WriteLine($"Error: {response.Error}");
    return;
}
Imports System

Dim response = Await a2pClient.HeadlessChrome.FromHtmlAsync(html)

If Not response.Success Then
    Console.WriteLine($"Error: {response.Error}")
    Return
End If
$vbLabelText   $csharpLabel

IronPDF模式:

try
{
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs("output.pdf");
}
catch (IronPdf.Exceptions.IronPdfLicenseException ex)
{
    Console.WriteLine($"License error: {ex.Message}");
}
catch (IronPdf.Exceptions.IronPdfRenderingException ex)
{
    Console.WriteLine($"Rendering error: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
try
{
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs("output.pdf");
}
catch (IronPdf.Exceptions.IronPdfLicenseException ex)
{
    Console.WriteLine($"License error: {ex.Message}");
}
catch (IronPdf.Exceptions.IronPdfRenderingException ex)
{
    Console.WriteLine($"Rendering error: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
Imports IronPdf.Exceptions

Try
    Dim renderer = New ChromePdfRenderer()
    Dim pdf = renderer.RenderHtmlAsPdf(html)
    pdf.SaveAs("output.pdf")
Catch ex As IronPdfLicenseException
    Console.WriteLine($"License error: {ex.Message}")
Catch ex As IronPdfRenderingException
    Console.WriteLine($"Rendering error: {ex.Message}")
Catch ex As Exception
    Console.WriteLine($"Error: {ex.Message}")
End Try
$vbLabelText   $csharpLabel

效能比較

指標 Api2pdf IronPDF
簡單的 HTML 2-5 秒 (網路) 100-500 毫秒(本地)
複雜頁面 5-10 秒 500ms-2s
每批 100 份 分鐘 (費率限制) 秒 (平行)
離線 無法提供 工作完全
冷開始 ~2s (第一次渲染)

效能最佳化秘訣

// 1. Reuse renderer instance
private static readonly ChromePdfRenderer SharedRenderer = new ChromePdfRenderer();

public PdfDocument GeneratePdf(string html)
{
    return SharedRenderer.RenderHtmlAsPdf(html);
}

// 2. Parallel generation
var tasks = htmlDocs.Select(html =>
    Task.Run(() => SharedRenderer.RenderHtmlAsPdf(html)));
var results = await Task.WhenAll(tasks);

// 3. Disable unnecessary features for speed
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = false; // If not needed
renderer.RenderingOptions.WaitFor.RenderDelay(0);   // No delay
// 1. Reuse renderer instance
private static readonly ChromePdfRenderer SharedRenderer = new ChromePdfRenderer();

public PdfDocument GeneratePdf(string html)
{
    return SharedRenderer.RenderHtmlAsPdf(html);
}

// 2. Parallel generation
var tasks = htmlDocs.Select(html =>
    Task.Run(() => SharedRenderer.RenderHtmlAsPdf(html)));
var results = await Task.WhenAll(tasks);

// 3. Disable unnecessary features for speed
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = false; // If not needed
renderer.RenderingOptions.WaitFor.RenderDelay(0);   // No delay
Imports System.Threading.Tasks

' 1. Reuse renderer instance
Private Shared ReadOnly SharedRenderer As New ChromePdfRenderer()

Public Function GeneratePdf(html As String) As PdfDocument
    Return SharedRenderer.RenderHtmlAsPdf(html)
End Function

' 2. Parallel generation
Dim tasks = htmlDocs.Select(Function(html) Task.Run(Function() SharedRenderer.RenderHtmlAsPdf(html)))
Dim results = Await Task.WhenAll(tasks)

' 3. Disable unnecessary features for speed
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = False ' If not needed
renderer.RenderingOptions.WaitFor.RenderDelay(0) ' No delay
$vbLabelText   $csharpLabel

排除常見的遷移問題

問題:PDF 看起來與Api2pdf輸出不同。

配合Api2pdf的 Headless Chrome 設定:

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
renderer.RenderingOptions.ViewPortWidth = 1280;
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.WaitFor.RenderDelay(1000);
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
renderer.RenderingOptions.ViewPortWidth = 1280;
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.WaitFor.RenderDelay(1000);
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print
renderer.RenderingOptions.PrintHtmlBackgrounds = True
renderer.RenderingOptions.ViewPortWidth = 1280
renderer.RenderingOptions.EnableJavaScript = True
renderer.RenderingOptions.WaitFor.RenderDelay(1000)
$vbLabelText   $csharpLabel

問題:外部資源無法載入

設定資源載入逾時:

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.AllFontsLoaded(timeout: 10000);
renderer.RenderingOptions.WaitFor.NetworkIdle(timeout: 10000);

// Or use base URL for relative paths
var pdf = renderer.RenderHtmlAsPdf(html, baseUrl: "https://example.com/");
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.AllFontsLoaded(timeout: 10000);
renderer.RenderingOptions.WaitFor.NetworkIdle(timeout: 10000);

// Or use base URL for relative paths
var pdf = renderer.RenderHtmlAsPdf(html, baseUrl: "https://example.com/");
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.WaitFor.AllFontsLoaded(timeout:=10000)
renderer.RenderingOptions.WaitFor.NetworkIdle(timeout:=10000)

' Or use base URL for relative paths
Dim pdf = renderer.RenderHtmlAsPdf(html, baseUrl:="https://example.com/")
$vbLabelText   $csharpLabel

問題:PDF 檔案大小過大

生成後壓縮圖像:

renderer.RenderingOptions.ImageQuality = 80;

// Or compress after generation
pdf.CompressImages(quality: 75);
pdf.SaveAs("compressed.pdf");
renderer.RenderingOptions.ImageQuality = 80;

// Or compress after generation
pdf.CompressImages(quality: 75);
pdf.SaveAs("compressed.pdf");
renderer.RenderingOptions.ImageQuality = 80

' Or compress after generation
pdf.CompressImages(quality:=75)
pdf.SaveAs("compressed.pdf")
$vbLabelText   $csharpLabel

遷移後檢查清單

完成程式碼遷移後,請驗證下列事項:

  • 驗證 PDF 輸出品質符合預期
  • 測試所有極端情況(大型文件、特殊字元)
  • 驗證績效指標(應有顯著改善)
  • 如果需要,更新 Docker 配置
  • 刪除Api2pdf入口網站帳戶和 API 金鑰
  • 更新監控(不再需要追蹤 API 延遲)
  • 為你的團隊記錄新模式
  • 更新 CI/CD 管線

讓您的 PDF 基礎架構面向未來

隨著 .NET 10 的臨近以及 C# 14 引入新的語言功能,選擇原生的 .NET PDF 函式庫可確保與不斷演進的執行時功能相容。IronPDF承諾支援最新的 .NET 版本,這意味著當專案延伸至 2025 年和 2026 年時,您的轉換投資將獲得回報 - 而無需持續累積每次轉換的成本。

其他資源


從Api2pdf轉移到IronPDF可將您的 PDF 生成從依賴雲端、每次轉換的成本模式轉變為本地、一次性投資。 您的敏感文件會保留在您的基礎架構上,延遲時間會從幾秒鐘降至幾毫秒鐘,而且您可以消除此重要應用程式功能對供應商的依賴。

Curtis Chau
技術作家

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

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

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我