如何用 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
或透過套件管理員控制台:
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
步驟 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" }
步驟 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()
完整的 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
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
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
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
將 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
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
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
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")
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")
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")
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)
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")
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
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
IronPDF 直接透過 BinaryData 或 Stream 返回 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
錯誤處理轉換
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
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
效能比較
| 指標 | 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
排除常見的遷移問題
問題: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)
問題:外部資源無法載入
設定資源載入逾時:
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/")
問題: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")
遷移後檢查清單
完成程式碼遷移後,請驗證下列事項:
- 驗證 PDF 輸出品質符合預期
- 測試所有極端情況(大型文件、特殊字元)
- 驗證績效指標(應有顯著改善)
- 如果需要,更新 Docker 配置
- 刪除Api2pdf入口網站帳戶和 API 金鑰
- 更新監控(不再需要追蹤 API 延遲)
- 為你的團隊記錄新模式
- 更新 CI/CD 管線
讓您的 PDF 基礎架構面向未來
隨著 .NET 10 的臨近以及 C# 14 引入新的語言功能,選擇原生的 .NET PDF 函式庫可確保與不斷演進的執行時功能相容。IronPDF承諾支援最新的 .NET 版本,這意味著當專案延伸至 2025 年和 2026 年時,您的轉換投資將獲得回報 - 而無需持續累積每次轉換的成本。
其他資源
從Api2pdf轉移到IronPDF可將您的 PDF 生成從依賴雲端、每次轉換的成本模式轉變為本地、一次性投資。 您的敏感文件會保留在您的基礎架構上,延遲時間會從幾秒鐘降至幾毫秒鐘,而且您可以消除此重要應用程式功能對供應商的依賴。

