跳至页脚内容
使用IRONPDF

用 C# 实现管理仪表盘的一键导出 PDF 功能

导出仪表盘的问题

IronPDF 主页 内部仪表盘的设计旨在通过网页浏览器查看。 一旦有人需要与外部人员分享文件,例如董事会会议演示文稿、领导团队的每周 KPI 快照或合规性审计报告,事情就会迅速恶化。

浏览器打印转 PDF 是人们首先尝试的方法,也是最先失败的方法。 页面会破坏图表,导航侧边栏会渗入布局,生成的 PDF 与实时仪表板完全不同。 屏幕截图的情况更糟:缩放到 A4 时分辨率会降低,文本无法搜索,而且多部分 KPI 视图很少能完整地显示在一张图片中而不丢失一半的数据。

更深层次的问题在于 JavaScript 渲染的图表。 由于 Chart.js、ApexCharts 和 Highcharts 都绘制在 HTML 上异步执行元素时,原生 HTML 到 PDF 快照通常会捕获空白画布。 HTML 内容存在于 DOM 中,但未被可视化。 这正是 IronPDF 能为您提供帮助的地方。

结果是,开发者每周一都会收到一条消息图标,要求他们手动提取并格式化报告。 这并非可扩展的工作流程。 今天,我们将通过一个 IronPDF 示例,了解它如何从 HTML 内容创建 PDF 文档。

解决方案:使用 IronPDF 实现服务器端仪表盘渲染

IronPDF 将驱动您仪表盘的 HTML 渲染为像素级精准的 PDF 文档。 用户点击"导出为 PDF"按钮(可能标有蓝色圆圈中的钥匙图标或蓝色钥匙图标),API 端点处理 HTML 转换逻辑,浏览器随后下载 PDF 内容。

无需部署 Puppeteer 旁路组件,无需管理 wkhtmltopdf 二进制文件,也无需付费和监控第三方导出 API。 IronPDF 作为用于处理 PDF 任务的 C# NuGet 库,可在您的现有 ASP.NET 应用程序中运行。 它内置了 Chromium 引擎,能够像真实浏览器一样执行 JavaScript,这意味着 Chart.js 和 ApexCharts 可以正确渲染,因为它们实际上是在页面被捕获之前就已运行。

导出按钮已成为一项自助功能,任何业务用户均可操作,无需开发人员介入。

实际应用示例

1. 用户点击"导出为 PDF"

仪表盘页面上的标准 JavaScript fetch 调用会将用户的当前筛选条件和日期范围发送至 API 端点,以协助生成 PDF 文档:

document.getElementById('export-btn').addEventListener('click', async () => {
    const params = new URLSearchParams({ from: dateFrom, to: dateTo, region: selectedRegion });
    const response = await fetch(`/api/reports/export?${params}`);
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'dashboard-report.pdf';
    a.click();
});
document.getElementById('export-btn').addEventListener('click', async () => {
    const params = new URLSearchParams({ from: dateFrom, to: dateTo, region: selectedRegion });
    const response = await fetch(`/api/reports/export?${params}`);
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'dashboard-report.pdf';
    a.click();
});
JAVASCRIPT

带有我们 JavaScript 代码的按钮

使用我们 JavaScript 代码的按钮 无需刷新页面,不进行重定向,仅从现有仪表板视图触发文件下载。

2. 服务器生成仪表盘 HTML 内容

控制器或服务层会查询用户在屏幕上看到的相同数据,并使用 KPI 卡片、数据表以及 Chart.js 或 ApexCharts 将执行的图表配置 JSON,填充 HTML 模板(无论是渲染后的 Razor 视图还是构建好的 HTML 字符串)。

HTML 代码可引用贵品牌的样式表,包含 IronSoftware 徽标,或使用 Iron Software 的客户徽标。 翻译内容还可包含 @media PRINT CSS 规则,用于隐藏导航元素并控制分页。

控制器文件示例

示例控制器文件

3. ChromePdfRenderer 在启用 JavaScript 的情况下渲染 HTML 文件或内容

这正是 IronPDF 发挥作用的地方。 EnableJavaScript = true 指示渲染器在捕获前执行脚本。 WaitFor.NetworkIdle0() 会保留快照,直到所有异步资源(包括通过 fetch 加载的图表数据)都已就绪。

通过 C# PDF DLL 安装 IronPDF 后,您可以使用以下代码:

using IronPdf;
using IronPdf.Rendering;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.EnableJavaScript = true;

renderer.RenderingOptions.WaitFor.NetworkIdle0();

renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;

renderer.RenderingOptions.MarginTop = 15;

renderer.RenderingOptions.MarginBottom = 15;

var pdf = renderer.RenderHtmlAsPdf(dashboardHtml);
using IronPdf;
using IronPdf.Rendering;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.EnableJavaScript = true;

renderer.RenderingOptions.WaitFor.NetworkIdle0();

renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;

renderer.RenderingOptions.MarginTop = 15;

renderer.RenderingOptions.MarginBottom = 15;

var pdf = renderer.RenderHtmlAsPdf(dashboardHtml);
Imports IronPdf
Imports IronPdf.Rendering

Dim renderer As New ChromePdfRenderer()

renderer.RenderingOptions.EnableJavaScript = True

renderer.RenderingOptions.WaitFor.NetworkIdle0()

renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print

renderer.RenderingOptions.MarginTop = 15

renderer.RenderingOptions.MarginBottom = 15

Dim pdf = renderer.RenderHtmlAsPdf(dashboardHtml)
$vbLabelText   $csharpLabel

对于图表通过定时器而非网络请求初始化的仪表盘,请将 NetworkIdle0() 替换为 WaitFor.JavaScript(),并在图表的 onComplete 回调中发出就绪信号。 无论采用哪种策略,都能确保 C# PDF 库在图表绘制完成后(而非绘制前)捕获该图表。

[{t:(将 CssMediaType 设置为 PRINT,以应用您的 @media print 样式表规则。 这使您能够在不修改实时仪表盘 HTML 的情况下,将侧边栏、导航栏和操作按钮从导出的 PDF 中隐藏。}}

4. 控制器将 PDF 文档作为文件返回供下载

该 API 端点将 PDF 内容封装在 FileContentResult 中。 无论您是 PDF 协会成员还是 AWS 合作伙伴网络用户,交付过程都将无缝衔接:

[HttpGet("api/reports/export")]

public IActionResult ExportDashboard([FromQuery] ReportFilters filters)

{

    var dashboardHtml = _reportService.BuildDashboardHtml(filters);

    var renderer = new ChromePdfRenderer();

    renderer.RenderingOptions.EnableJavaScript = true;

    renderer.RenderingOptions.WaitFor.NetworkIdle0();

    renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

    PdfDocument report = renderer.RenderHtmlAsPdf(dashboardHtml);

    return File(

        report.BinaryData,

        "application/pdf",

        $"KPI-Report-{filters.From:yyyyMMdd}.pdf"

    );

}
[HttpGet("api/reports/export")]

public IActionResult ExportDashboard([FromQuery] ReportFilters filters)

{

    var dashboardHtml = _reportService.BuildDashboardHtml(filters);

    var renderer = new ChromePdfRenderer();

    renderer.RenderingOptions.EnableJavaScript = true;

    renderer.RenderingOptions.WaitFor.NetworkIdle0();

    renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;

    PdfDocument report = renderer.RenderHtmlAsPdf(dashboardHtml);

    return File(

        report.BinaryData,

        "application/pdf",

        $"KPI-Report-{filters.From:yyyyMMdd}.pdf"

    );

}
Imports Microsoft.AspNetCore.Mvc
Imports IronPdf

<HttpGet("api/reports/export")>
Public Function ExportDashboard(<FromQuery> filters As ReportFilters) As IActionResult

    Dim dashboardHtml = _reportService.BuildDashboardHtml(filters)

    Dim renderer = New ChromePdfRenderer()

    renderer.RenderingOptions.EnableJavaScript = True

    renderer.RenderingOptions.WaitFor.NetworkIdle0()

    renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print

    Dim report As PdfDocument = renderer.RenderHtmlAsPdf(dashboardHtml)

    Return File(report.BinaryData, "application/pdf", $"KPI-Report-{filters.From:yyyyMMdd}.pdf")

End Function
$vbLabelText   $csharpLabel

Content-Disposition: attachment 由 File() 方法根据文件名自动设置,因此浏览器会触发下载操作,而非在新标签页中打开 PDF。

已下载的 PDF 文件

使用 IronPDF 示例代码生成 PDF 报告

5. 可选:定时报告分发

同一渲染调用可在后台作业、Hangfire 周期性任务或托管 IHostedService 中运行,该服务每周一早晨生成周度 KPI PDF 文件,并将其通过电子邮件发送至管理层分发列表。无需用户交互。

实际好处

面向企业用户的自助服务。一旦导出按钮上线,Slack 上的"能帮我导出个报告吗?"这类消息就会停止。任何拥有仪表盘访问权限的用户均可自行下载 PDF,无需提交请求。

图表还原度。由于 Chromium 在 IronPDF 内部执行 JavaScript,Chart.js、ApexCharts 和 Highcharts 生成的图表在 PDF 中呈现的效果与屏幕上完全一致——包括颜色、以静态标签形式呈现的工具提示,以及响应式尺寸调整。

品牌一致性。每份导出的报告均采用仪表盘样式表中定义的公司徽标、配色方案和字体样式。 导出与分发之间不涉及任何格式调整步骤。

定时生成。将渲染调用与后台任务关联,自动每周或每月通过电子邮件向利益相关者发送 PDF 文件。 管理层将收到一份经过精心润色的报告,而无需任何人手动生成。

无外部依赖。IronPDF 在进程内运行。 无需维持 Puppeteer Node.js 进程的运行,无需针对不同平台打包 wkhtmltopdf 二进制文件,也不存在带有速率限制或按文档计费的 SaaS 导出 API。

针对打印优化的布局。CssMediaType.PRINT 在渲染时应用您的 @media PRINT 规则,让您能够在 CSS 中定义简洁的、专用于导出的布局,而无需维护单独的 HTML 模板。

结语

在管理仪表盘中添加一个"导出为 PDF"按钮,听起来似乎是个微不足道的小功能。 实际上,它消除了重复的手动操作,为非技术用户提供了他们多年来一直试图绕过的问题的解决方案,并生成了一份能真实反映数据外观的文档,而非PRINT对话框中那种残缺的近似效果。

IronPDF 负责处理渲染过程中的复杂操作——包括 JavaScript 执行、CSS 媒体类型以及图表捕获——因此您只需在客户端实现一个控制器操作和一个 HTML 模板即可。 如果您想在自己的仪表盘上进行测试,可访问 IronPDF.com 获取 30 天试用版,该版本功能齐全且无水印。

Curtis Chau
技术作家

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

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

钢铁支援团队

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