You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C# Asp.net中保留Bootstrap 4布局及自定义CSS生成PDF?

解决方案:Asp.NET Core生成带Bootstrap布局的PDF(替代DinkToPdf)

我完全理解你的困扰——DinkToPdf依赖的wkhtmltopdf引擎对Bootstrap 4的Flexbox、Grid这类现代CSS特性支持很差,导致表格变形、内容溢出的问题太常见了。下面给你两个经过验证的解决方案,既能完美保留你的Bootstrap布局和自定义CSS,又能生成高质量的PDF:


方案1:PuppeteerSharp(首选,完美支持现代CSS)

PuppeteerSharp是Chrome/Chromium的.NET封装,它用真实的浏览器引擎渲染HTML,所以对Bootstrap、自定义CSS的支持和浏览器完全一致,不会出现布局变形的问题。

实现步骤:

  1. 安装NuGet包

    Install-Package PuppeteerSharp
    
  2. 编写PartialView渲染工具方法
    先把你的统计数据PartialView转换成HTML字符串:

    private string RenderPartialViewToString(string viewName, object model)
    {
        using var sw = new StringWriter();
        var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        var viewContext = new ViewContext(
            ControllerContext, 
            viewResult.View,
            new ViewDataDictionary(model), 
            new TempDataDictionary(), 
            sw
        );
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
    
  3. 生成PDF的核心代码

    public async Task<IActionResult> GenerateStatsPdf()
    {
        // 1. 获取你的统计数据模型
        var statsModel = FetchYourStatisticsData(); // 替换成你的数据获取逻辑
    
        // 2. 渲染PartialView为HTML字符串
        var partialHtml = RenderPartialViewToString("_StatsPartial", statsModel);
    
        // 3. 构造完整HTML(注入Bootstrap和自定义CSS)
        var fullHtml = $@"
        <html>
            <head>
                <meta charset='UTF-8'>
                <!-- 引入Bootstrap 4 CSS -->
                <link href='https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css' rel='stylesheet'>
                <!-- 你的自定义CSS -->
                <style>
                    .custom-stat-card {{
                        margin-bottom: 1.5rem;
                        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                    }}
                    .stat-table {{
                        width: 100%;
                        table-layout: fixed;
                    }}
                    /* 其他自定义样式... */
                </style>
            </head>
            <body class='container mt-4'>
                {partialHtml}
            </body>
        </html>";
    
        // 4. 使用PuppeteerSharp生成PDF
        await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
        using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
        using var page = await browser.NewPageAsync();
    
        // 设置页面尺寸(匹配A4纸)
        await page.SetViewportAsync(new ViewPortOptions { Width = 827, Height = 1170 });
        // 加载HTML内容
        await page.SetContentAsync(fullHtml);
    
        // 生成PDF(开启打印背景,否则Bootstrap的背景样式不显示)
        var pdfBytes = await page.PdfDataAsync(new PdfOptions
        {
            Format = PuppeteerSharp.Media.PaperFormat.A4,
            MarginOptions = new MarginOptions { Top = "20px", Bottom = "20px", Left = "20px", Right = "20px" },
            PrintBackground = true
        });
    
        // 返回PDF文件供下载
        return File(pdfBytes, "application/pdf", "Statistics_Report.pdf");
    }
    

优势:

  • 100%支持Bootstrap 4的Flexbox、Grid布局,自定义CSS也能完美渲染
  • 生成的PDF和浏览器预览效果完全一致
  • 支持JavaScript(如果你的PartialView有动态渲染逻辑)

方案2:iText7 + html2pdf(成熟PDF库,商业场景友好)

如果你需要更轻量的方案,或者在商业项目中使用,iText7的html2pdf模块对现代CSS的支持也远优于DinkToPdf,而且是业界成熟的PDF处理库。

实现步骤:

  1. 安装NuGet包

    Install-Package iText7
    Install-Package iText7.html2pdf
    
  2. 生成PDF的核心代码

    public IActionResult GenerateStatsPdfWithiText()
    {
        var statsModel = FetchYourStatisticsData();
        var partialHtml = RenderPartialViewToString("_StatsPartial", statsModel);
    
        var fullHtml = $@"
        <html>
            <head>
                <meta charset='UTF-8'>
                <link href='https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css' rel='stylesheet'>
                <style>
                    /* 你的自定义样式 */
                </style>
            </head>
            <body class='container mt-4'>
                {partialHtml}
            </body>
        </html>";
    
        using var ms = new MemoryStream();
        var writer = new PdfWriter(ms);
        var document = new iText.Kernel.Pdf.PdfDocument(writer);
        document.SetDefaultPageSize(iText.Kernel.Geom.PageSize.A4);
    
        // 设置字体提供者,避免中文乱码(如果需要支持中文)
        var converterProps = new ConverterProperties();
        converterProps.SetFontProvider(new DefaultFontProvider(true, true, true));
    
        // 转换HTML到PDF
        HtmlConverter.ConvertToPdf(fullHtml, document, converterProps);
        document.Close();
    
        return File(ms.ToArray(), "application/pdf", "Statistics_Report_iText.pdf");
    }
    

注意事项:

  • iText7的开源版本采用AGPL协议,商业项目使用需要购买商业授权
  • 对极复杂的JavaScript渲染支持不如PuppeteerSharp,但纯CSS布局完全没问题

(可选)DinkToPdf的临时妥协方案(不推荐)

如果你暂时不想换库,可以尝试以下临时修复,但效果有限:

  • 给表格添加table-layout: fixed样式,强制表格宽度适应页面
  • 禁用Bootstrap的Flexbox类,改用传统的float布局重构PartialView
  • 手动调整容器和元素的宽度,避免内容溢出

但这些方法都是治标不治本,长期来看还是推荐更换到上面两种方案。


内容的提问来源于stack exchange,提问作者Fred11_

火山引擎 最新活动