Bootstrap Blazor中使用PuppeteerSharp对HTML截图

PuppeteerSharp是一个基于.NET的库,提供了对Puppeteer的C#支持,用于自动化,可用于测试、截图、爬虫等任务。

官网:Puppeteer Sharp(感觉文章中有些代码段没有更新,直接用会有报错)。

本篇文章是对HTML截图的实现,无需在页面或容器中展示html中的实际内容。请前往NuGet中自行下载PuppeteerSharp库(本次演示用的是20.0.5版本),并在代码中引用。

复制代码
//razor中使用
@using PuppeteerSharp
@using PuppeteerSharp.Media

复制代码
//cs中使用
using PuppeteerSharp;
using PuppeteerSharp.Media;

注意PuppeteerSharp库20.0.5版本的依赖性:

1、razor添加一个截图按钮

复制代码
<Button OnClick="OnClickToTakeAnScreenshot">截图</Button>

如果需要加载展示html的内容,可以使用iframe:

复制代码
<iframe id="iframeHtml" src="./files/xxx.html" style="width:100%;height:100%;"></iframe>

2、注入IWebHostEnvironment和DownloadService

复制代码
//用于找WebRootPath
[Inject]
[NotNull]
private IWebHostEnvironment _env { get; set; }

//用于下载截取后的图片
[Inject]
[NotNull]
private DownloadService _downloadService { get; set; }

3、生成HTML文件路径和截图后图片存放路径

复制代码
//files在wwwroot目录下面
string htmlPath = Path.Combine(_env.WebRootPath, "files/xxx.html");
string imagePath = Path.Combine(_env.WebRootPath, "files/screenshot.png");

4、下载和管理浏览器的可执行文件

复制代码
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();

DownloadAsync方法默认下载Chrome浏览器的可执行文件,并且会校验目标文件是否存在,如果存在则不会重新下载,下载并解压成功后,会自动创建两个目录:

由于存在网络问题,下载失败后,可以多尝试几次。

5、创建无头浏览器和page实例

复制代码
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
    Headless = true //无头浏览器配置
});
var page = await browser.NewPageAsync();

6、读取和加载HTML文件

复制代码
await page.GoToAsync(htmlPath);

//等待几秒,确保html中的内容加载完毕
Thread.Sleep(3000);

await等待GoToAsync方法只是让html文件读取完,但是里面的数据填充、渲染等还另外需要时间,最好等待几秒(根据html文件大小自行计算),让里面的内容加载完成,再进行后面的操作,否则截的图会有内容缺失。

7、开启视窗模式(如有需要,可自行添加和修改)

复制代码
await page.SetViewportAsync(new ViewPortOptions
{
    Width = 1000,
    Height = 800
});

需要设置视窗的宽度和高度,相当于限定了加载html的父容器尺寸,转为特定宽高。如果没有这段代码,默认是全屏。

8、截取特定的区域(如有需要,可自行添加和修改)

复制代码
// 定义要截取的区域
var clip = new Clip
{
    X = 150,      // 截图区域的左上角 X 坐标
    Y = 150,      // 截图区域的左上角 Y 坐标
    Width = 500,  // 截图区域的宽度
    Height = 350  // 截图区域的高度
};

9、截取并保存

复制代码
await page.ScreenshotAsync(imagePath, new ScreenshotOptions
{
    Clip = clip
});

10、下载截取的图片

复制代码
await using var stream = File.OpenRead(imagePath);

DownloadOption downloadOption = new DownloadOption();
downloadOption.FileName = Path.GetFileName(imagePath);
downloadOption.FileStream = stream;
await _downloadService.DownloadFromStreamAsync(downloadOption);

截图按钮OnClickToTakeAnScreenshot的完整方法代码如下:

复制代码
@using PuppeteerSharp
@using PuppeteerSharp.Media

<div>
    <Button OnClick="OnClickToTakeAnScreenshot">截图</Button>
</div>

@code {
    [Inject]
    [NotNull]
    protected IWebHostEnvironment _env { get; set; }

    [Inject]
    [NotNull]
    protected DownloadService _downloadService { get; set; }

    private async Task OnClickToTakeAnScreenshot()
    {
        try
        {
            string htmlPath = Path.Combine(_env.WebRootPath, "files/xxx.html");
            string imagePath = Path.Combine(_env.WebRootPath, "files/screenshot.png");

            var browserFetcher = new BrowserFetcher();
            await browserFetcher.DownloadAsync();

            var browser = await Puppeteer.LaunchAsync(new LaunchOptions
            {
                Headless = true
            });
            var page = await browser.NewPageAsync();
            await page.GoToAsync(htmlPath);

            Thread.Sleep(3000);

            await page.SetViewportAsync(new ViewPortOptions
            {
               Width = 1000,
               Height = 800
            });

            // 定义要截取的区域
            var clip = new Clip
            {
                X = 150,      // 截图区域的左上角 X 坐标
                Y = 150,      // 截图区域的左上角 Y 坐标
                Width = 500,  // 截图区域的宽度
                Height = 350  // 截图区域的高度
            };

            await page.ScreenshotAsync(imagePath, new ScreenshotOptions
            {
                Clip = clip
            });

            await using var stream = File.OpenRead(imagePath);

            DownloadOption downloadOption = new DownloadOption();
            downloadOption.FileName = Path.GetFileName(imagePath);
            downloadOption.FileStream = stream;
            await _downloadService.DownloadFromStreamAsync(downloadOption);

            _MsgBox.Show("截图成功!", AlertTypes.Success);
        }
        catch (Exception ex)
        {
            _MsgBox.Show(ex.Message, AlertTypes.Error);
        }
    }
}
相关推荐
佳腾_2 分钟前
【web服务_负载均衡Nginx】一、Nginx 基础与核心概念解析
前端·nginx·负载均衡
风中飘爻8 分钟前
MySQL入门:数据操作CURD
前端·bootstrap·html
rocky19116 分钟前
谷歌浏览器插件 录制元素拖动事件
前端·javascript
emoji11111140 分钟前
vue3、原生html交互传值
vue.js·html·交互
nothingbutluck46441 分钟前
2025.4.10 html有序、无序、定义列表、音视频标签
前端·html·音视频
爱上python的猴子1 小时前
chrome中的copy xpath 与copy full xpath的区别
前端·chrome
许泽宇的技术分享2 小时前
.NET MCP 文档
人工智能·.net
Lysun0012 小时前
dispaly: inline-flex 和 display: flex 的区别
前端·javascript·css
山禾女鬼0012 小时前
Vue 3 自定义指令
前端·javascript·vue.js
啊卡无敌2 小时前
Vue 3 reactive 和 ref 区别及 失去响应性问题
前端·javascript·vue.js