Bootstrap Blazor中使用PuppeteerSharp对HTML截图

发布于:2024-12-19 ⋅ 阅读:(12) ⋅ 点赞:(0)

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);
        }
    }
}