跳至页脚内容
使用IRONPDF

Xamarin PDF生成器:使用IronPDF构建移动PDF应用

在Xamarin.Forms中创建PDF文件可能很棘手。 大多数 .NET PDF 库不直接支持移动应用程序,尝试在设备上生成 PDF 文档通常会导致错误或功能缺失。 这时IronPDF就派上用场了。

虽然 IronPDF 不能在 Xamarin.Forms 应用程序中原生运行,但服务器端 API 方法可以很好地弥补这一差距。 您的移动应用向 API 发送 HTML 内容,并接收生成的 PDF 文件——让您可以访问专业的 PDF 生成功能,包括表单、页眉、页脚、图像和自定义布局。

重要提示:微软已于 2024 年 5 月停止对 Xamarin 的支持。对于新项目,建议使用.NET MAUI作为替代方案,它能更直接地支持 IronPDF。 本指南涵盖了仍在维护中的传统 Xamarin 项目的服务器端模式,并解释了从头开始的团队迁移到 MAUI 的路径。

为什么服务器端方法适用于移动端 PDF 生成?

IronPDF 擅长将 HTML 内容转换为精美的 PDF 文档,并完全支持 CSS、JavaScript 和复杂布局。 在专用服务器上运行 IronPDF(而不是在移动应用程序内运行)可以绕过平台限制,从而避免 iOS 和 Android 设备上直接渲染 PDF。

服务器端模式具有以下几个实际优势:

-输出一致:字体、图像和 CSS 在服务器端解析,消除了 Android 和 iOS 硬件之间的渲染差异。 -功能访问: IronPDF 的所有功能,如 PDF 表单创建、数字签名、水印和多页布局,均可在服务器上无限制使用。 -更轻便的移动应用:设备仅发送 HTTP 请求并存储返回的 PDF 字节 - 手机上无需运行繁重的 PDF 引擎。 -集中式许可:一个IronPDF 许可证即可覆盖您的服务器部署,而无需为每个设备单独授权。

Xamarin.Forms 客户端调用 API,接收字节数组,将其写入本地存储,并可选择打开 PDF 查看器。 其他一切都由服务器处理。

如何设置 IronPDF PDF 生成 API?

首先创建一个 ASP.NET Core Web API 项目。 这是一个标准的 .NET 10 最小 API,您可以将其托管在任何地方——Azure 应用服务、AWS、本地服务器或 Docker 容器。

安装IronPDF

您可以使用以下任一命令从 NuGet 安装 IronPDF

Install-Package IronPdf
dotnet add package IronPdf
Install-Package IronPdf
dotnet add package IronPdf
SHELL

创建 PDF 控制器

安装 IronPDF 后,添加一个接受 HTML 并返回 PDF 的控制器:

using IronPdf;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();

namespace PdfGenerationApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class PdfController : ControllerBase
    {
        [HttpPost("generate")]
        public async Task<IActionResult> GeneratePdf([FromBody] PdfRequest request)
        {
            var renderer = new ChromePdfRenderer();
            renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
            renderer.RenderingOptions.MarginTop = 25;
            renderer.RenderingOptions.MarginBottom = 25;
            renderer.RenderingOptions.MarginLeft = 20;
            renderer.RenderingOptions.MarginRight = 20;

            var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
            return File(pdf.BinaryData, "application/pdf", "document.pdf");
        }
    }

    public class PdfRequest
    {
        public string HtmlContent { get; set; } = string.Empty;
    }
}
using IronPdf;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();

namespace PdfGenerationApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class PdfController : ControllerBase
    {
        [HttpPost("generate")]
        public async Task<IActionResult> GeneratePdf([FromBody] PdfRequest request)
        {
            var renderer = new ChromePdfRenderer();
            renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
            renderer.RenderingOptions.MarginTop = 25;
            renderer.RenderingOptions.MarginBottom = 25;
            renderer.RenderingOptions.MarginLeft = 20;
            renderer.RenderingOptions.MarginRight = 20;

            var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
            return File(pdf.BinaryData, "application/pdf", "document.pdf");
        }
    }

    public class PdfRequest
    {
        public string HtmlContent { get; set; } = string.Empty;
    }
}
Imports IronPdf
Imports Microsoft.AspNetCore.Mvc

Dim builder = WebApplication.CreateBuilder(args)
builder.Services.AddControllers()
Dim app = builder.Build()
app.MapControllers()
app.Run()

Namespace PdfGenerationApi.Controllers
    <ApiController>
    <Route("api/[controller]")>
    Public Class PdfController
        Inherits ControllerBase

        <HttpPost("generate")>
        Public Async Function GeneratePdf(<FromBody> request As PdfRequest) As Task(Of IActionResult)
            Dim renderer = New ChromePdfRenderer()
            renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4
            renderer.RenderingOptions.MarginTop = 25
            renderer.RenderingOptions.MarginBottom = 25
            renderer.RenderingOptions.MarginLeft = 20
            renderer.RenderingOptions.MarginRight = 20

            Dim pdf = Await renderer.RenderHtmlAsPdfAsync(request.HtmlContent)
            Return File(pdf.BinaryData, "application/pdf", "document.pdf")
        End Function
    End Class

    Public Class PdfRequest
        Public Property HtmlContent As String = String.Empty
    End Class
End Namespace
$vbLabelText   $csharpLabel

ChromePdfRenderer 使用基于 Chromium 的引擎来渲染 HTML,就像现代浏览器一样。 HTML 转 PDF 转换会保留 CSS 动画、嵌入式字体、SVG 图形和 JavaScript 生成的内容。 纸张尺寸和页边距设置会直接影响最终文档的布局。

添加页眉和页脚

对于专业文档,请在调用渲染器之前添加页眉和页脚

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right; font-size:12px; color:#555;'>Confidential -- Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center; font-size:11px;'>Generated by MyCompany App</div>"
};
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:right; font-size:12px; color:#555;'>Confidential -- Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:center; font-size:11px;'>Generated by MyCompany App</div>"
};
Imports System

renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='text-align:right; font-size:12px; color:#555;'>Confidential -- Page {page} of {total-pages}</div>",
    .DrawDividerLine = True
}

renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='text-align:center; font-size:11px;'>Generated by MyCompany App</div>"
}
$vbLabelText   $csharpLabel

页码标记(例如 {page}{total-pages})在渲染时会自动解析。

如何实现 Xamarin 客户端?

在 Xamarin.Forms 应用程序中,创建一个调用 API 的服务类。 保持服务简洁——它的唯一任务是序列化 HTML 有效负载,发送它,并将原始 PDF 字节返回给调用者。

using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace XamarinPdfApp.Services
{
    public class PdfService
    {
        private readonly HttpClient _httpClient;
        private const string ApiUrl = "https://your-api.example.com/api/pdf/generate";

        public PdfService()
        {
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(60)
            };
        }

        public async Task<byte[]> GeneratePdfAsync(string htmlContent)
        {
            var payload = new { HtmlContent = htmlContent };
            var json = JsonSerializer.Serialize(payload);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync(ApiUrl, content);

            if (response.IsSuccessStatusCode)
                return await response.Content.ReadAsByteArrayAsync();

            var error = await response.Content.ReadAsStringAsync();
            throw new InvalidOperationException($"PDF generation failed ({(int)response.StatusCode}): {error}");
        }
    }
}
using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace XamarinPdfApp.Services
{
    public class PdfService
    {
        private readonly HttpClient _httpClient;
        private const string ApiUrl = "https://your-api.example.com/api/pdf/generate";

        public PdfService()
        {
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(60)
            };
        }

        public async Task<byte[]> GeneratePdfAsync(string htmlContent)
        {
            var payload = new { HtmlContent = htmlContent };
            var json = JsonSerializer.Serialize(payload);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync(ApiUrl, content);

            if (response.IsSuccessStatusCode)
                return await response.Content.ReadAsByteArrayAsync();

            var error = await response.Content.ReadAsStringAsync();
            throw new InvalidOperationException($"PDF generation failed ({(int)response.StatusCode}): {error}");
        }
    }
}
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json

Namespace XamarinPdfApp.Services
    Public Class PdfService
        Private ReadOnly _httpClient As HttpClient
        Private Const ApiUrl As String = "https://your-api.example.com/api/pdf/generate"

        Public Sub New()
            _httpClient = New HttpClient With {
                .Timeout = TimeSpan.FromSeconds(60)
            }
        End Sub

        Public Async Function GeneratePdfAsync(htmlContent As String) As Task(Of Byte())
            Dim payload = New With {Key .HtmlContent = htmlContent}
            Dim json = JsonSerializer.Serialize(payload)
            Dim content = New StringContent(json, Encoding.UTF8, "application/json")

            Dim response = Await _httpClient.PostAsync(ApiUrl, content)

            If response.IsSuccessStatusCode Then
                Return Await response.Content.ReadAsByteArrayAsync()
            End If

            Dim error = Await response.Content.ReadAsStringAsync()
            Throw New InvalidOperationException($"PDF generation failed ({CInt(response.StatusCode)}): {error}")
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

60 秒超时时间可以处理包含大量图像或 CSS 资源的复杂 HTML 文档。 对于非常大的文件,可以考虑从 API 返回预签名的下载 URL,而不是直接流式传输二进制文件——这样可以保持移动内存使用量的可预测性。

如何在设备上保存和打开PDF文件?

服务返回字节数组后,将其写入设备存储,并在平台 PDF 查看器中打开。 Xamarin.Forms 使用 DependencyService 模式来调用特定于平台的实现。

在共享代码中定义接口:

using System.Threading.Tasks;

namespace XamarinPdfApp.Interfaces
{
    public interface ISaveFile
    {
        Task<string> SavePdfAsync(string filename, byte[] pdfData);
    }
}
using System.Threading.Tasks;

namespace XamarinPdfApp.Interfaces
{
    public interface ISaveFile
    {
        Task<string> SavePdfAsync(string filename, byte[] pdfData);
    }
}
Imports System.Threading.Tasks

Namespace XamarinPdfApp.Interfaces
    Public Interface ISaveFile
        Function SavePdfAsync(filename As String, pdfData As Byte()) As Task(Of String)
    End Interface
End Namespace
$vbLabelText   $csharpLabel

使用 DependencyService 注册 iOS 实现:

using Foundation;
using QuickLook;
using UIKit;
using XamarinPdfApp.Interfaces;
using Xamarin.Forms;

[assembly: Dependency(typeof(XamarinPdfApp.iOS.SaveFileIOS))]
namespace XamarinPdfApp.iOS
{
    public class SaveFileIOS : ISaveFile
    {
        public async Task<string> SavePdfAsync(string filename, byte[] pdfData)
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var filePath = System.IO.Path.Combine(documents, filename);
            await System.IO.File.WriteAllBytesAsync(filePath, pdfData);
            return filePath;
        }
    }
}
using Foundation;
using QuickLook;
using UIKit;
using XamarinPdfApp.Interfaces;
using Xamarin.Forms;

[assembly: Dependency(typeof(XamarinPdfApp.iOS.SaveFileIOS))]
namespace XamarinPdfApp.iOS
{
    public class SaveFileIOS : ISaveFile
    {
        public async Task<string> SavePdfAsync(string filename, byte[] pdfData)
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var filePath = System.IO.Path.Combine(documents, filename);
            await System.IO.File.WriteAllBytesAsync(filePath, pdfData);
            return filePath;
        }
    }
}
Imports Foundation
Imports QuickLook
Imports UIKit
Imports XamarinPdfApp.Interfaces
Imports Xamarin.Forms

<Assembly: Dependency(GetType(XamarinPdfApp.iOS.SaveFileIOS))>
Namespace XamarinPdfApp.iOS
    Public Class SaveFileIOS
        Implements ISaveFile

        Public Async Function SavePdfAsync(filename As String, pdfData As Byte()) As Task(Of String) Implements ISaveFile.SavePdfAsync
            Dim documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
            Dim filePath = System.IO.Path.Combine(documents, filename)
            Await System.IO.File.WriteAllBytesAsync(filePath, pdfData)
            Return filePath
        End Function
    End Class
End Namespace
$vbLabelText   $csharpLabel

对于 Android,写入应用程序的外部文件目录,并在清单中注册 FileProvider,以便您可以将 URI 传递给 PDF 查看器意图。 共享代码中的 DependencyService.Get<ISaveFile>() 调用会在运行时检索当前平台注册的任何实现。

将所有部件连接起来

在 Xamarin.Forms 页面或 ViewModel 中,将服务和平台保存器结合起来:

var htmlContent = BuildInvoiceHtml(invoice);
var pdfBytes = await _pdfService.GeneratePdfAsync(htmlContent);
var saver = DependencyService.Get<ISaveFile>();
var filePath = await saver.SavePdfAsync("invoice.pdf", pdfBytes);
await Launcher.OpenAsync(new OpenFileRequest
{
    File = new ReadOnlyFile(filePath, "application/pdf")
});
var htmlContent = BuildInvoiceHtml(invoice);
var pdfBytes = await _pdfService.GeneratePdfAsync(htmlContent);
var saver = DependencyService.Get<ISaveFile>();
var filePath = await saver.SavePdfAsync("invoice.pdf", pdfBytes);
await Launcher.OpenAsync(new OpenFileRequest
{
    File = new ReadOnlyFile(filePath, "application/pdf")
});
Dim htmlContent = BuildInvoiceHtml(invoice)
Dim pdfBytes = Await _pdfService.GeneratePdfAsync(htmlContent)
Dim saver = DependencyService.Get(Of ISaveFile)()
Dim filePath = Await saver.SavePdfAsync("invoice.pdf", pdfBytes)
Await Launcher.OpenAsync(New OpenFileRequest With {
    .File = New ReadOnlyFile(filePath, "application/pdf")
})
$vbLabelText   $csharpLabel

这将使用用户已安装的任何查看器打开已保存的 PDF 文件,在 iOS 和 Android 上通常是原生 PDF 应用程序。

如何生成专业的发票和报告PDF文件?

PDF文件的质量几乎完全取决于传递给渲染器的HTML模板的质量。 使用 C# 字符串插值或像 Scriban 这样的模板库来构建数据驱动的 HTML:

public string BuildInvoiceHtml(Invoice invoice)
{
    var rows = string.Join(
        "\n",
        invoice.项目s.Select(i =>
            $"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.UnitPrice:F2}</td><td>${i.Total:F2}</td></tr>"
        )
    );

    return $@"<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<style>
  body {{ font-family: Arial, sans-serif; color: #333; margin: 0; padding: 30px; }}
  h1 {{ color: #1a73e8; }}
  table {{ width: 100%; border-collapse: collapse; margin-top: 20px; }}
  th {{ background: #1a73e8; color: #fff; padding: 10px; text-align: left; }}
  td {{ padding: 10px; border-bottom: 1px solid #e0e0e0; }}
  .total {{ font-weight: bold; font-size: 1.1em; text-align: right; margin-top: 15px; }}
</style>
</head>
<body>
  <h1>Invoice #{invoice.Number}</h1>
  <p>Date: {invoice.Date:yyyy-MM-dd} &nbsp;|&nbsp; Due: {invoice.DueDate:yyyy-MM-dd}</p>
  <p>Bill to: <strong>{invoice.ClientName}</strong></p>
  <table>
    <thead><tr><th>项目</th><th>Qty</th><th>Unit Price</th><th>Total</th></tr></thead>
    <tbody>{rows}</tbody>
  </table>
  <p class='total'>Grand Total: ${invoice.GrandTotal:F2}</p>
</body>
</html>";
}
public string BuildInvoiceHtml(Invoice invoice)
{
    var rows = string.Join(
        "\n",
        invoice.项目s.Select(i =>
            $"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.UnitPrice:F2}</td><td>${i.Total:F2}</td></tr>"
        )
    );

    return $@"<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<style>
  body {{ font-family: Arial, sans-serif; color: #333; margin: 0; padding: 30px; }}
  h1 {{ color: #1a73e8; }}
  table {{ width: 100%; border-collapse: collapse; margin-top: 20px; }}
  th {{ background: #1a73e8; color: #fff; padding: 10px; text-align: left; }}
  td {{ padding: 10px; border-bottom: 1px solid #e0e0e0; }}
  .total {{ font-weight: bold; font-size: 1.1em; text-align: right; margin-top: 15px; }}
</style>
</head>
<body>
  <h1>Invoice #{invoice.Number}</h1>
  <p>Date: {invoice.Date:yyyy-MM-dd} &nbsp;|&nbsp; Due: {invoice.DueDate:yyyy-MM-dd}</p>
  <p>Bill to: <strong>{invoice.ClientName}</strong></p>
  <table>
    <thead><tr><th>项目</th><th>Qty</th><th>Unit Price</th><th>Total</th></tr></thead>
    <tbody>{rows}</tbody>
  </table>
  <p class='total'>Grand Total: ${invoice.GrandTotal:F2}</p>
</body>
</html>";
}
Imports System
Imports System.Linq

Public Class InvoiceHtmlBuilder
    Public Function BuildInvoiceHtml(invoice As Invoice) As String
        Dim rows = String.Join(
            vbLf,
            invoice.项目s.Select(Function(i) $"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.UnitPrice:F2}</td><td>${i.Total:F2}</td></tr>")
        )

        Return $"<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<style>
  body {{ font-family: Arial, sans-serif; color: #333; margin: 0; padding: 30px; }}
  h1 {{ color: #1a73e8; }}
  table {{ width: 100%; border-collapse: collapse; margin-top: 20px; }}
  th {{ background: #1a73e8; color: #fff; padding: 10px; text-align: left; }}
  td {{ padding: 10px; border-bottom: 1px solid #e0e0e0; }}
  .total {{ font-weight: bold; font-size: 1.1em; text-align: right; margin-top: 15px; }}
</style>
</head>
<body>
  <h1>Invoice #{invoice.Number}</h1>
  <p>Date: {invoice.Date:yyyy-MM-dd} &nbsp;|&nbsp; Due: {invoice.DueDate:yyyy-MM-dd}</p>
  <p>Bill to: <strong>{invoice.ClientName}</strong></p>
  <table>
    <thead><tr><th>项目</th><th>Qty</th><th>Unit Price</th><th>Total</th></tr></thead>
    <tbody>{rows}</tbody>
  </table>
  <p class='total'>Grand Total: ${invoice.GrandTotal:F2}</p>
</body>
</html>"
    End Function
End Class
$vbLabelText   $csharpLabel

ChromePdfRenderer 会像浏览器一样渲染此模板。 您可以使用IronPDF 的水印 API添加水印,或者为机密草稿应用自定义水印设计。 对于需要签名字段的文档, IronPDF 的签名支持功能允许您在服务器端嵌入数字签名占位符。

如何在 Xamarin 应用中处理 PDF 表单?

PDF 表单是移动商务应用程序的常见需求——合同、入职问卷和检查清单都可以从预先填写的可编辑字段中受益。 服务器 API 可以接受 HTML 模板中的字段数据,并在返回 PDF 之前嵌入表单值:

[HttpPost("form")]
public async Task<IActionResult> GenerateForm([FromBody] FormRequest request)
{
    var renderer = new ChromePdfRenderer();
    // Render an HTML form template to create an interactive PDF form
    var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlTemplate);

    // Fill known values before returning
    var form = pdf.Form;
    foreach (var field in request.FieldValues)
    {
        var pdfField = form.Fields.FirstOrDefault(f => f.Name == field.Key);
        if (pdfField is IronPdf.Forms.PdfFormTextFieldField textField)
            textField.Value = field.Value;
    }

    return File(pdf.BinaryData, "application/pdf", "form.pdf");
}
[HttpPost("form")]
public async Task<IActionResult> GenerateForm([FromBody] FormRequest request)
{
    var renderer = new ChromePdfRenderer();
    // Render an HTML form template to create an interactive PDF form
    var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlTemplate);

    // Fill known values before returning
    var form = pdf.Form;
    foreach (var field in request.FieldValues)
    {
        var pdfField = form.Fields.FirstOrDefault(f => f.Name == field.Key);
        if (pdfField is IronPdf.Forms.PdfFormTextFieldField textField)
            textField.Value = field.Value;
    }

    return File(pdf.BinaryData, "application/pdf", "form.pdf");
}
Imports Microsoft.AspNetCore.Mvc
Imports IronPdf

<HttpPost("form")>
Public Async Function GenerateForm(<FromBody> request As FormRequest) As Task(Of IActionResult)
    Dim renderer As New ChromePdfRenderer()
    ' Render an HTML form template to create an interactive PDF form
    Dim pdf = Await renderer.RenderHtmlAsPdfAsync(request.HtmlTemplate)

    ' Fill known values before returning
    Dim form = pdf.Form
    For Each field In request.FieldValues
        Dim pdfField = form.Fields.FirstOrDefault(Function(f) f.Name = field.Key)
        If TypeOf pdfField Is IronPdf.Forms.PdfFormTextFieldField Then
            Dim textField = DirectCast(pdfField, IronPdf.Forms.PdfFormTextFieldField)
            textField.Value = field.Value
        End If
    Next

    Return File(pdf.BinaryData, "application/pdf", "form.pdf")
End Function
$vbLabelText   $csharpLabel

移动客户端发送一个包含字段名称和值的字典。 服务器会填写这些信息,并返回一个表单,用户可以查看该表单,在 PDF 查看器中填写任何剩余字段,然后提交。

如何从 Xamarin 应用程序中提取文本并合并 PDF?

除了生成文档之外,IronPDF 还支持多种文档操作,您可以将其公开为 API 端点:

-从 PDF 中提取文本解析 PDF 内容以索引文档或预填充数据输入表单。 -合并或拆分 PDF将多个报告合并到一个 PDF 中,或将一个大文档拆分成按章节的文件。 -将 PDF 转换为图像将 PDF 页面渲染为 PNG 或 JPEG 缩略图,以便在移动 UI 中预览。

它们各自成为一个独立的 API 端点。 Xamarin 客户端像调用任何其他 REST 资源一样调用它们,使移动代码不包含 PDF 逻辑,并使服务器成为权威的文档处理器。

常见问题有哪些?如何解决?

服务器-客户端架构虽然简单明了,但有几个生产环境方面的问题需要注意:

Xamarin 与 IronPDF API 集成常见问题及推荐解决方案
问题原因推荐修复
请求超时包含大量远程资源的复杂 HTML 代码渲染速度较慢。增加HttpClient.Timeout值,并在渲染选项中设置服务器端渲染超时时间。
PDF 内存占用激增通过响应正文流式传输 20 MB 的 PDF 文件上传到 Blob 存储并返回一个短期有效的下载 URL
离线生成当用户请求 PDF 文件时,设备没有网络连接。将请求排队到本地,并在连接恢复后重试。
未经授权的 API 访问端点对互联网开放使用 JWT 或 API 密钥进行安全保护;强制所有路由使用 HTTPS
字体未嵌入服务器操作系统未安装字体。将字体以 base64 数据 URI 或 CSS @font-face规则的形式嵌入到 HTML 中
iOS 存储权限该应用针对 iOS 14 及更高版本,并采用更严格的沙盒机制。写入应用程序沙箱内的Environment.SpecialFolder.MyDocuments

对于速率限制,可以使用AspNetCoreRateLimit等库在 ASP.NET Core 端添加中间件。 记录每次生成请求的时间数据,以便您在慢速模板影响用户之前发现它们。

是否应该从 Xamarin 迁移到 .NET MAUI?

如果您计划在 2026 年启动一个新的移动项目,那么 .NET MAUI 是理想之选。微软已于 2024 年 5 月停止对 Xamarin 的支持,这意味着不会再有安全补丁或漏洞修复。 .NET MAUI 是其直接继任者,运行在 .NET 10 上,与当前的 IronPDF 运行时相匹配。

本指南中描述的服务器端架构同样适用于 .NET MAUI 应用程序——客户端 HTTP 代码本质上是相同的; 只有 DependencyService 被 MAUI 的内置依赖注入所替换。 维护现有 Xamarin 应用的团队应该计划迁移到 MAUI; 微软官方的 .NET MAUI 迁移指南详细记录了迁移步骤。

如何在生产环境中部署和授权 IronPDF?

部署非常简单:使用 Docker 将 ASP.NET Core API 容器化,然后将其推送到 Azure 应用服务、AWS ECS 或任何 Kubernetes 集群。 IronPDF许可证密钥已设置为服务器上的环境变量:

IronPdf.License.LicenseKey = Environment.GetEnvironmentVariable("IRONPDF_LICENSE_KEY")
    ?? throw new InvalidOperationException("IronPDF license key not set.");
IronPdf.License.LicenseKey = Environment.GetEnvironmentVariable("IRONPDF_LICENSE_KEY")
    ?? throw new InvalidOperationException("IronPDF license key not set.");
Imports System
Imports IronPdf

IronPdf.License.LicenseKey = If(Environment.GetEnvironmentVariable("IRONPDF_LICENSE_KEY"), Throw New InvalidOperationException("IronPDF license key not set."))
$vbLabelText   $csharpLabel

请查看IronPDF 许可页面,选择适合您部署的级别。 免费试用许可证允许您在购买前测试所有功能。 对于容器化或无服务器部署,请检查许可证级别是否涵盖同时运行的服务器实例数量。

获得许可后,您可以查阅IronPDF 文档,了解高级配置选项,包括线程安全渲染设置、PDF/A 合规性和辅助功能标记。

生产部署检查清单

基于 IronPDF 的 PDF 生成 API 部署清单
项目建议
许可证密钥存储在环境变量或密钥管理器中,切勿存储在源代码中。
HTTPS对所有 API 端点强制执行 TLS;切勿通过纯 HTTP 发送 HTML 负载。
身份验证使用 JWT 持有者令牌或 API 密钥;一旦发生违规行为,立即撤销。
缓存将相同的 HTML 有效负载缓存一个较短的 TTL,以减少冗余渲染。
缩放IronPDF 是线程安全的;可以在负载均衡器后运行多个 API 副本。
监控跟踪渲染延迟和错误率;当数值高于基线时发出警报。

服务器端模式可以水平扩展,而无需对 Xamarin 或 MAUI 客户端进行任何更改。 随着 PDF 生成量的增长,增加副本,并依靠负载均衡器均匀分配请求。

常见问题解答

IronPDF可以在Xamarin.Forms中原生使用吗?

IronPDF不能在Xamarin.Forms中原生运行,但可以通过服务器端方法集成以处理PDF创建和操作。

在移动应用中使用IronPDF进行PDF生成有哪些好处?

使用IronPDF可以创建PDF文件、填写表单、处理多页,并包含图像、字体和自定义布局,增强移动应用的PDF生成功能。

IronPDF如何在Xamarin中处理PDF创建?

IronPDF使用服务器端方法在Xamarin中生成PDF,支持移动设备上通常不支持的复杂PDF功能。

在Xamarin中可以使用IronPDF填写PDF表单吗?

是的,IronPDF支持在Xamarin应用中填充PDF表单,作为其高级PDF处理功能的一部分。

IronPDF在Xamarin PDF生成方面解决了哪些挑战?

IronPDF通过使用服务器端解决方案,解决了在移动设备上直接生成PDF时出现的错误和功能缺失问题。

IronPDF能否在Xamarin应用的PDF中处理自定义布局?

是的,IronPDF可以在生成的PDF中包含自定义布局,让您控制文档的设计和展示。

使用IronPDF可以在Xamarin中实现哪种PDF功能?

IronPDF允许在Xamarin中实现多页文档、表单填充、图像和字体嵌入、以及自定义布局的功能。

为什么推荐在Xamarin中使用IronPDF进行PDF生成时采用服务器端方法?

推荐使用服务器端方法是因为它绕过了移动设备的限制,确保可靠的PDF创建和高级功能。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我