You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor WebAssembly中用Puppeteer Sharp生成PDF报错求助

解决Blazor WebAssembly中使用Puppeteer Sharp生成PDF的平台不支持问题

你遇到的问题核心是Blazor WebAssembly的运行环境限制:

  • Blazor WASM运行在浏览器沙箱内,没有权限启动本地浏览器进程(Puppeteer需要启动Chrome/Chromium实例)。
  • Puppeteer Sharp的BrowserFetcher内部使用了System.Net.WebClient,而这个类在WASM平台上被禁用,即使替换成HttpClient,也无法解决浏览器内无法启动本地进程的本质问题。

下面给出两种可行的解决方案:

方案一:后端生成PDF(推荐,支持复杂页面)

将PDF生成逻辑移到ASP.NET Core后端,前端通过API请求获取生成好的PDF文件,这是最可靠的方案,因为后端服务器环境完全支持Puppeteer Sharp的所有功能。

步骤1:后端添加API接口

在你的ASP.NET Core项目中创建API控制器,实现PDF生成逻辑:

using Microsoft.AspNetCore.Mvc;
using PuppeteerSharp;

[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
    [HttpPost("generate")]
    public async Task<IActionResult> GeneratePdf([FromBody] PdfRequest request)
    {
        // 下载浏览器(首次运行自动下载,后续可缓存)
        using var browserFetcher = new BrowserFetcher();
        await browserFetcher.DownloadAsync();

        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
        await using var page = await browser.NewPageAsync();
        
        // 加载目标页面(支持传入URL或直接传入HTML内容)
        if (!string.IsNullOrEmpty(request.Url))
        {
            await page.GoToAsync(request.Url, new NavigationOptions { WaitUntil = WaitUntilNavigation.Networkidle0 });
        }
        else if (!string.IsNullOrEmpty(request.HtmlContent))
        {
            await page.SetContentAsync(request.HtmlContent);
        }
        
        // 等待字体加载完成
        await page.EvaluateExpressionHandleAsync("document.fonts.ready");
        
        // 生成PDF字节流
        var pdfBytes = await page.PdfAsync(new PdfOptions
        {
            Format = PaperFormat.A4,
            PrintBackground = true // 确保背景样式被渲染
        });

        // 返回PDF文件给前端
        return File(pdfBytes, "application/pdf", $"document_{DateTime.Now:yyyyMMddHHmmss}.pdf");
    }
}

// 请求模型
public class PdfRequest
{
    public string? Url { get; set; }
    public string? HtmlContent { get; set; }
}

步骤2:Blazor前端调用API并下载PDF

在Blazor组件中通过HttpClient调用后端API,触发浏览器下载:

@inject HttpClient Http
<button @onclick="GenerateAndDownloadPdf">生成PDF</button>

@code {
    private async Task GenerateAndDownloadPdf()
    {
        // 可传入Razor页面URL或直接传入页面HTML内容
        var request = new { Url = "https://your-domain.com/your-razor-page" };
        
        var response = await Http.PostAsJsonAsync("api/pdf/generate", request);
        response.EnsureSuccessStatusCode();
        
        // 获取PDF字节流
        var pdfBytes = await response.Content.ReadAsByteArrayAsync();
        
        // 调用JS互操作触发下载
        await JS.InvokeVoidAsync("downloadFile", pdfBytes, "my-document.pdf", "application/pdf");
    }
}

在wwwroot/index.html中添加对应的JS代码:

function downloadFile(byteArray, fileName, contentType) {
    const blob = new Blob([byteArray], { type: contentType });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}

方案二:前端直接生成PDF(适合简单页面)

如果不想依赖后端,可以用前端JS库(如jsPDF + html2canvas)直接在浏览器中将DOM转换为PDF,无需Puppeteer。

步骤1:引入JS库

在wwwroot/index.html中添加CDN链接:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>

步骤2:Blazor组件中调用JS生成PDF

<div id="pdf-content">
    <!-- 这里是要转换为PDF的Razor页面内容 -->
    <h1>我的PDF内容</h1>
    <p>这是一段测试文本</p>
</div>

<button @onclick="GeneratePdfInBrowser">前端生成PDF</button>

@code {
    [Inject] private IJSRuntime JS { get; set; }

    private async Task GeneratePdfInBrowser()
    {
        await JS.InvokeVoidAsync("generatePdfFromElement", "pdf-content");
    }
}

添加对应的JS代码:

async function generatePdfFromElement(elementId) {
    const element = document.getElementById(elementId);
    const canvas = await html2canvas(element, { scale: 2 }); // 提高生成清晰度
    const imgData = canvas.toDataURL('image/png');
    
    const pdf = new jspdf.jsPDF('p', 'mm', 'a4');
    const pageWidth = pdf.internal.pageSize.getWidth();
    const pageHeight = pdf.internal.pageSize.getHeight();
    const imgWidth = canvas.width / 2;
    const imgHeight = canvas.height / 2;
    
    // 计算缩放比例,确保内容适配PDF页面
    const scale = Math.min(pageWidth / imgWidth, pageHeight / imgHeight);
    const scaledWidth = imgWidth * scale;
    const scaledHeight = imgHeight * scale;
    
    pdf.addImage(imgData, 'PNG', (pageWidth - scaledWidth) / 2, 10, scaledWidth, scaledHeight);
    pdf.save('my-document.pdf');
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:41:11