Telerik Document Processing與IronPDF:技術比較指南
.NET 8 引入的運行時更改導致與許多傳統PDF程式庫不相容。 System.Drawing.Common在非Windows平台上已被棄用,Native AOT對依賴反射的程式庫施加了新的限制,容器優先的部署模式暴露了在Windows開發機器上未顯現的依賴問題。 在.NET Framework甚至.NET 6上運行的程式庫可能在.NET 8中出現PlatformNotSupportedException錯誤。
本文件描述了哪些PDF程式庫可以與.NET 8一起工作,展示了不相容程式庫中會遇到的具體錯誤,並提供了Docker和Azure Functions的部署配置。
快速入門: 在.NET 8中從HTML生成PDF
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
var pdf = renderer.RenderHtmlAsPdf(@"
<html>
<head><style>
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
h1 { color: #2563eb; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #2563eb; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style></head>
<body>
<h1>Q4 Report</h1>
<table>
<tr><th>Metric</th><th>Value</th><th>Change</th></tr>
<tr><td>Revenue</td><td>$1.2M</td><td>+12%</td></tr>
<tr><td>Users</td><td>45,230</td><td>+23%</td></tr>
</table>
</body></html>");
pdf.SaveAs("report.pdf");using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
var pdf = renderer.RenderHtmlAsPdf(@"
<html>
<head><style>
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
h1 { color: #2563eb; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #2563eb; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style></head>
<body>
<h1>Q4 Report</h1>
<table>
<tr><th>Metric</th><th>Value</th><th>Change</th></tr>
<tr><td>Revenue</td><td>$1.2M</td><td>+12%</td></tr>
<tr><td>Users</td><td>45,230</td><td>+23%</td></tr>
</table>
</body></html>");
pdf.SaveAs("report.pdf");Imports IronPdf
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4
Dim pdf = renderer.RenderHtmlAsPdf("
<html>
<head><style>
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
h1 { color: #2563eb; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background: #2563eb; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style></head>
<body>
<h1>Q4 Report</h1>
<table>
<tr><th>Metric</th><th>Value</th><th>Change</th></tr>
<tr><td>Revenue</td><td>$1.2M</td><td>+12%</td></tr>
<tr><td>Users</td><td>45,230</td><td>+23%</td></tr>
</table>
</body></html>")
pdf.SaveAs("report.pdf")通過NuGet安裝: Install-Package IronPdf。 直接在net8.0上運行,無需額外配置。 可部署到Windows、Linux、macOS、Docker和Azure,無需平台特定的設置。
為什麼較舊的PDF程式庫在.NET 8中會失敗?
iText— 與.NET 8不相容
iText(iText的原始.NET移植)自2018年以來未更新。它僅目標.NET Framework:
錯誤 NU1202: 套件iTextSharp 5.5.13與net8.0不兼容遷移路徑是iText,但它有不同的API並且需要AGPL合規(開源整個應用程式)或商業授權。 價格未公開 — 第三方資料顯示每年$15,000到$210,000。
wkhtmltopdf 包裝器 — 在.NET 8中的DLL載入失敗
圍繞wkhtmltopdf的C#包裝器(DinkToPdf、Rotativa、NReco.PdfGenerator)在.NET 8的部署模式中出現平台特定錯誤:
DinkToPdf — 找不到本地程式庫:
System.DllNotFoundException:無法載入DLL 'libwkhtmltox'Rotativa.AspNetCore — 需要手動二進制路徑配置,這與.NET 8的容器優先部署相衝突:
// This pattern requires deploying wkhtmltopdf binaries alongside your app
// and breaks in Docker containers without explicit path configuration
RotativaConfiguration.Setup(env.WebRootPath, "wkhtmltopdf");// This pattern requires deploying wkhtmltopdf binaries alongside your app
// and breaks in Docker containers without explicit path configuration
RotativaConfiguration.Setup(env.WebRootPath, "wkhtmltopdf");' This pattern requires deploying wkhtmltopdf binaries alongside your app
' and breaks in Docker containers without explicit path configuration
RotativaConfiguration.Setup(env.WebRootPath, "wkhtmltopdf")TuesPechkin / NReco — 架構不匹配:
System.BadImageFormatException: 無法加載文件或組件這些錯誤反映了更深層次的問題: wkhtmltopdf於2024年7月被存檔且有未修補的CVE。 本地二進制架構早於.NET 8的平台檢測改進。 沒有解決方案 - 只能遷移到其他程式庫。
PDFSharp— 在Linux上System.Drawing.Common失敗
PDFSharp依賴於System.Drawing.Common,微軟已在.NET 6中棄用該功能於非Windows平台。在.NET 8中,這會在部署到Linux或Docker時產生運行時失敗:
using PdfSharp.Pdf;
using PdfSharp.Drawing;
var document = new PdfDocument();
// PlatformNotSupportedException on Linux:
// System.Drawing.Common is not supported on this platformusing PdfSharp.Pdf;
using PdfSharp.Drawing;
var document = new PdfDocument();
// PlatformNotSupportedException on Linux:
// System.Drawing.Common is not supported on this platformImports PdfSharp.Pdf
Imports PdfSharp.Drawing
Dim document As New PdfDocument()
' PlatformNotSupportedException on Linux:
' System.Drawing.Common is not supported on this platformPDFSharp 6.x一直在努力去除這一依賴,但截至2026年初,跨平台支持仍不完整。對於僅限Windows的部署,PDFSharp與.NET 8相容。對於Linux、Docker或雲部署,它是不可靠的。
哪些PDF程式庫可以與.NET 8一起工作?
IronPDF— 完整.NET 8支持,跨平台
IronPDF直接目標net8.0並嵌入了Chromium渲染。 沒有System.Drawing.Common依賴,沒有本地二進制管理,沒有平台特定的配置。
最小API整合(主要的.NET 8模式):
using IronPdf;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/invoice/{id}/pdf", async (int id, InvoiceService service) =>
{
var invoice = await service.GetInvoiceAsync(id);
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoice.ToHtml());
return Results.File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf");
});
app.Run();using IronPdf;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/invoice/{id}/pdf", async (int id, InvoiceService service) =>
{
var invoice = await service.GetInvoiceAsync(id);
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoice.ToHtml());
return Results.File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf");
});
app.Run();Imports IronPdf
Dim builder = WebApplication.CreateBuilder(args)
Dim app = builder.Build()
app.MapGet("/invoice/{id}/pdf", Async Function(id As Integer, service As InvoiceService)
Dim invoice = Await service.GetInvoiceAsync(id)
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(invoice.ToHtml())
Return Results.File(pdf.BinaryData, "application/pdf", $"invoice-{id}.pdf")
End Function)
app.Run()對於使用控制器模式的團隊,相同的程式碼可在控制器動作內運行 — RenderHtmlAsPdf 返回一個PdfDocument 您可以通過.BinaryData將其轉換為位元。
授權: 永久授權起價$2,998(Lite — 1位開發者,1個專案)。 專業版: $1,499(10位開發者)。 企業版: $2,999(無限)。 發佈於 ironpdf.com。
QuestPDF— .NET 8相容,無HTML
QuestPDF可與.NET 8一起使用,無平台依賴。 其流暢的C# API以程式方式構建文件 — 無HTML解析器,無CSS引擎,無瀏覽器引擎:
using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
QuestPDF.Settings.License = LicenseType.Community; // Free under $1M revenue
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(col =>
{
col.Item().Text("Q4 Report").FontSize(24).Bold();
col.Item().Table(table =>
{
table.ColumnsDefinition(c => { c.RelativeColumn(2); c.RelativeColumn(1); c.RelativeColumn(1); });
table.Header(h =>
{
h.Cell().Text("Metric").Bold();
h.Cell().Text("Value").Bold();
h.Cell().Text("Change").Bold();
});
table.Cell().Text("Revenue"); table.Cell().Text("$1.2M"); table.Cell().Text("+12%");
table.Cell().Text("Users"); table.Cell().Text("45,230"); table.Cell().Text("+23%");
});
});
});
}).GeneratePdf("report.pdf");using QuestPDF.Fluent;
using QuestPDF.Infrastructure;
QuestPDF.Settings.License = LicenseType.Community; // Free under $1M revenue
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Content().Column(col =>
{
col.Item().Text("Q4 Report").FontSize(24).Bold();
col.Item().Table(table =>
{
table.ColumnsDefinition(c => { c.RelativeColumn(2); c.RelativeColumn(1); c.RelativeColumn(1); });
table.Header(h =>
{
h.Cell().Text("Metric").Bold();
h.Cell().Text("Value").Bold();
h.Cell().Text("Change").Bold();
});
table.Cell().Text("Revenue"); table.Cell().Text("$1.2M"); table.Cell().Text("+12%");
table.Cell().Text("Users"); table.Cell().Text("45,230"); table.Cell().Text("+23%");
});
});
});
}).GeneratePdf("report.pdf");Imports QuestPDF.Fluent
Imports QuestPDF.Infrastructure
QuestPDF.Settings.License = LicenseType.Community ' Free under $1M revenue
Document.Create(Sub(container)
container.Page(Sub(page)
page.Size(PageSizes.A4)
page.Margin(2, Unit.Centimetre)
page.Content().Column(Sub(col)
col.Item().Text("Q4 Report").FontSize(24).Bold()
col.Item().Table(Sub(table)
table.ColumnsDefinition(Sub(c)
c.RelativeColumn(2)
c.RelativeColumn(1)
c.RelativeColumn(1)
End Sub)
table.Header(Sub(h)
h.Cell().Text("Metric").Bold()
h.Cell().Text("Value").Bold()
h.Cell().Text("Change").Bold()
End Sub)
table.Cell().Text("Revenue")
table.Cell().Text("$1.2M")
table.Cell().Text("+12%")
table.Cell().Text("Users")
table.Cell().Text("45,230")
table.Cell().Text("+23%")
End Sub)
End Sub)
End Sub)
End Sub).GeneratePdf("report.pdf")QuestPDF不轉換HTML。 如果您的工作流程使用HTML模板(Razor視圖,儀表盤導出,網頁內容歸檔),您需要其他程式庫。 社區授權涵蓋年收入低於$1M的企業; 超出此範圍則需要商業授權。
iText— .NET 8相容,AGPL授權
iText(iText的後繼者)支持.NET 8。pdfHTML附加組件提供HTML到PDF轉換,帶有自定義解析器 — 而不是瀏覽器引擎,因此現代CSS功能(Flexbox,Grid)無法正確渲染。
授權: 用於開源使用的AGPL,對於專有應用的商業授權(訂閱,價格未公開)。 iText於2024年轉為訂閱制商業授權。
Docker部署
標準Debian映像(推薦)
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
# IronPDF works without additional apt-get installs
# Chromium dependencies are handled internally
COPY --from=build /app/publish .
ENV DOTNET_RUNNING_IN_CONTAINER=true
EXPOSE 8080
ENTRYPOINT ["dotnet", "MyApp.dll"]Alpine映像(佔用更小空間)
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /src
COPY ["MyApp.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
WORKDIR /app
# Alpine requires explicit Chromium dependencies
RUN apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "MyApp.dll"]Debian映像不需要額外的套件。 Alpine映像較小,但需要顯式安裝Chromium程式庫。 對於大多數部署來說,標準Debian映像更簡單且更可靠。
Azure Functions(獨立工作者)
.NET 8的Azure Functions使用獨立工作者模型。 IronPDF可在此模型中工作以按需生成PDF:
using IronPdf;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespace MyApp.Functions;
public class PdfFunctions
{
[Function("GenerateInvoice")]
public async Task<HttpResponseData> GenerateInvoice(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
{
var invoice = await req.ReadFromJsonAsync<InvoiceRequest>();
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice));
var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/pdf");
response.Headers.Add("Content-Disposition",
$"attachment; filename=invoice-{invoice.Id}.pdf");
await response.Body.WriteAsync(pdf.BinaryData);
return response;
}
private string BuildInvoiceHtml(InvoiceRequest invoice)
{
return $@"<html><body>
<h1>Invoice #{invoice.Id}</h1>
<p>Amount: ${invoice.Amount:F2}</p>
</body></html>";
}
}
public record InvoiceRequest(string Id, decimal Amount);using IronPdf;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespace MyApp.Functions;
public class PdfFunctions
{
[Function("GenerateInvoice")]
public async Task<HttpResponseData> GenerateInvoice(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
{
var invoice = await req.ReadFromJsonAsync<InvoiceRequest>();
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice));
var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/pdf");
response.Headers.Add("Content-Disposition",
$"attachment; filename=invoice-{invoice.Id}.pdf");
await response.Body.WriteAsync(pdf.BinaryData);
return response;
}
private string BuildInvoiceHtml(InvoiceRequest invoice)
{
return $@"<html><body>
<h1>Invoice #{invoice.Id}</h1>
<p>Amount: ${invoice.Amount:F2}</p>
</body></html>";
}
}
public record InvoiceRequest(string Id, decimal Amount);Imports IronPdf
Imports Microsoft.Azure.Functions.Worker
Imports Microsoft.Azure.Functions.Worker.Http
Namespace MyApp.Functions
Public Class PdfFunctions
<Function("GenerateInvoice")>
Public Async Function GenerateInvoice(
<HttpTrigger(AuthorizationLevel.Function, "post")> req As HttpRequestData) As Task(Of HttpResponseData)
Dim invoice = Await req.ReadFromJsonAsync(Of InvoiceRequest)()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(BuildInvoiceHtml(invoice))
Dim response = req.CreateResponse(System.Net.HttpStatusCode.OK)
response.Headers.Add("Content-Type", "application/pdf")
response.Headers.Add("Content-Disposition", $"attachment; filename=invoice-{invoice.Id}.pdf")
Await response.Body.WriteAsync(pdf.BinaryData)
Return response
End Function
Private Function BuildInvoiceHtml(invoice As InvoiceRequest) As String
Return $"<html><body>
<h1>Invoice #{invoice.Id}</h1>
<p>Amount: ${invoice.Amount:F2}</p>
</body></html>"
End Function
End Class
Public Class InvoiceRequest
Public Property Id As String
Public Property Amount As Decimal
Public Sub New(id As String, amount As Decimal)
Me.Id = id
Me.Amount = amount
End Sub
End Class
End Namespace部署考慮: IronPDF的Chromium二進製文件會增加約200MB到部署包中。 Azure Functions消耗計劃有1.5GB的部署大小限制 — 驗證您的總包大小。對於高級或專用計劃,此限制不適用。 對於第一次PDF生成的冷啟動延遲為2-5秒,因為Chromium正在初始化。
Native AOT相容性
.NET 8擴展了Native AOT支持,但PDF程式庫面臨基本限制。 基於Chromium的程式庫(如IronPDF、Puppeteer Sharp)無法編譯為AOT,因為它們嵌入或生成瀏覽器進程。 iText使用大量反射,與修剪衝突。
當前狀態<PublishAot>true</PublishAot>:
| 程式庫 | AOT 狀態 | 原因 |
|---|---|---|
| IronPDF | 不相容 | 嵌入了Chromium運行時 |
| iText | 不相容 | 大量反射,動態程式碼生成 |
| QuestPDF | 部分(TrimMode=partial 可用) | 一些反射使用 |
| PDFSharp | 不相容 | System.Drawing.Common依賴 |
如果Native AOT是一個硬性要求,QuestPDF與TrimMode=partial 是最接近的選擇 — 但僅限於從資料程式生成文件,而非HTML轉換。 對於HTML到PDF場景,當前沒有程式庫是與AOT可行的。
授權比較
| 程式庫 | 模式 | 成本 | .NET 8 支持 |
|---|---|---|---|
| IronPDF | 永久 | $2,998 (Lite) / $1,499 (Pro) / $2,999 (Enterprise) | 完整 |
| iText | AGPL或訂閱 | 未發布(估計$15K–$210K/年) | 完整 |
| QuestPDF | 社區 / 商業 | 免費 < $1M 收入,之後商業 | 完整 |
| PDFSharp | MIT (免費) | $0 | 僅限Windows(Linux不完整) |
| Aspose.PDF | 每開發者 | 約$999+ | 完整(Linux記憶體問題) |
.NET 9 向前相容性
.NET 9(2025年11月發布)繼續沿用了.NET 8建立的模式。可與.NET 8一起工作的程式庫通常無需更改即可與.NET 9一起工作。 與PDF生成相關的.NET 9的主要新增功能是改進的ARM64性能(使基於Chromium的渲染在Apple Silicon和AWS Graviton上受益)和持續改進的Native AOT(雖然PDF程式庫的基本限制仍然存在)。
如果您目標是.NET 9或計劃升級,選擇完全支持.NET 8跨平台部署的程式庫是最安全的路徑。 存在平台特定問題的程式庫(Linux上的PDFSharp,與libgdiplus的Aspose)不太可能在NET 9中解決這些問題,因為底層的依賴棄用是永久的。
遷移指南
從iText到IronPDF
// Before (iTextSharp — doesn't compile against net8.0)
using iTextSharp.text;
using iTextSharp.text.pdf;
var doc = new Document();
PdfWriter.GetInstance(doc, new FileStream("output.pdf", FileMode.Create));
doc.Open();
doc.Add(new Paragraph("Hello World"));
doc.Close();
// After (IronPDF — targets net8.0)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<p>Hello World</p>");
pdf.SaveAs("output.pdf");// Before (iTextSharp — doesn't compile against net8.0)
using iTextSharp.text;
using iTextSharp.text.pdf;
var doc = new Document();
PdfWriter.GetInstance(doc, new FileStream("output.pdf", FileMode.Create));
doc.Open();
doc.Add(new Paragraph("Hello World"));
doc.Close();
// After (IronPDF — targets net8.0)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<p>Hello World</p>");
pdf.SaveAs("output.pdf");Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports IronPdf
Imports System.IO
' Before (iTextSharp — doesn't compile against net8.0)
Dim doc As New Document()
PdfWriter.GetInstance(doc, New FileStream("output.pdf", FileMode.Create))
doc.Open()
doc.Add(New Paragraph("Hello World"))
doc.Close()
' After (IronPDF — targets net8.0)
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<p>Hello World</p>")
pdf.SaveAs("output.pdf")從wkhtmltopdf包裝器到IronPDF
// Before (DinkToPdf — DllNotFoundException on .NET 8)
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlContent = html } }
};
var bytes = converter.Convert(doc);
// After (IronPDF — native .NET 8 support)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
var bytes = pdf.BinaryData;// Before (DinkToPdf — DllNotFoundException on .NET 8)
var converter = new SynchronizedConverter(new PdfTools());
var doc = new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlContent = html } }
};
var bytes = converter.Convert(doc);
// After (IronPDF — native .NET 8 support)
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
var bytes = pdf.BinaryData;Imports IronPdf
' Before (DinkToPdf — DllNotFoundException on .NET 8)
Dim converter = New SynchronizedConverter(New PdfTools())
Dim doc = New HtmlToPdfDocument With {
.Objects = {New ObjectSettings With {.HtmlContent = html}}
}
Dim bytes = converter.Convert(doc)
' After (IronPDF — native .NET 8 support)
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
bytes = pdf.BinaryData兩者API表面更簡單。 主要的遷移成本是測試您現有的HTML模板,以確保輸出符合預期。
推薦
對於需要HTML到PDF轉換的.NET 8專案: IronPDF提供嵌入的Chromium渲染,無需配置即可跨平台運行。 它直接支持Docker部署、Azure Functions和Linux容器。
對於從資料程式生成文件的.NET 8專案: QuestPDF的流暢API設計良好,與.NET 8相容,社區授權涵蓋了大部分初創企業和小型團隊。
對於在Windows上進行PDF操作(合併、拆分、表單): 若您的部署目標僅限Windows,PDFSharp仍然是可行的。
避免使用iText(不相容)、wkhtmltopdf包裝器(已存檔,有CVE)和任何依賴System.Drawing.Common以跨平台部署的程式庫。
[(Aspose, DinkToPdf, NReco, PDFSharp, PuppeteerSharp, QuestPDF, Rotativa, TuesPechkin, iText, 和wkhtmltopdf是其各自所有者的註冊商標。 本網站與Aspose Pty Ltd, CodeFlint, DinkToPdf, NReco, PuppeteerSharp, Rotativa, TuesPechkin, empira Software GmbH,iTextGroup, 或 wkhtmltopdf無關,亦未獲其支持或贊助。 所有產品名稱、商標和品牌均為其各自所有者的財產。 比較僅供資訊參考,反映撰寫時公開可用的資訊。)
