我可以使用 ScreenshotAsync 方法将屏幕截图保存到内存而不是磁盘吗?

Can I use the ScreenshotAsync method to save the screenshot to memory instead of disk?

我正在使用 PuppeteerSharp 从本地托管的 HTML 模板生成 PDF,并希望 PDF 不可搜索,这意味着 PDF 实际上只是 PDF 中的一个大图像。我之所以选择采用这种方法,是因为我想让文档更难被篡改。

我已经想到了一种生成纯图像 PDF 的技术。我访问并截取 HTML 页面的屏幕截图,将其存储到磁盘,从浏览器访问所述屏幕截图,最后从该图像生成 PDF。 PDF 结果很好,但我想了解是否可以消除将图像存储到磁盘的需要。

代码如下:

函数代码

[FunctionName("pdftest")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
            ILogger log)
        {
            log.LogInformation($"Browser path: {appInfo.BrowserExecutablePath}");

            ViewPortOptions vprtOpts = new ViewPortOptions()
            {
                DeviceScaleFactor = 2
            };

            var browser = await Puppeteer.LaunchAsync(new LaunchOptions
            {
                Headless = true,
                ExecutablePath = appInfo.BrowserExecutablePath,
                DefaultViewport = vprtOpts
            });

            var page = await browser.NewPageAsync();
            // access the HTML template
            await page.GoToAsync(@"C:\experiment\pdf\index.html");

            // where to save the screenshot
            var file = @"C:\experiment\pdf\index.png";

            // where to save the final PDF
            var file2 = @"C:\experiment\pdf\index2.pdf";
            PdfOptions opts = new PdfOptions()
            {
                PrintBackground = true,
                Width = "794px",
                Height = "1122px",
                Scale = 1
            };

            ScreenshotOptions scrOpts = new ScreenshotOptions()
            {
                FullPage = true,
            };

            await page.ScreenshotAsync(file, scrOpts);
            await page.GoToAsync(@"C:\experiment\pdf\index.png");
            var stream = await page.PdfStreamAsync(opts);
            await page.PdfAsync(file2, opts);
            await browser.CloseAsync();

            return new FileStreamResult(stream, "application/pdf");
        }

Startup.cs

public class Startup : FunctionsStartup
{

    public override void Configure(IFunctionsHostBuilder builder)
    {
        var bfOptions = new BrowserFetcherOptions();
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            bfOptions.Path = Path.GetTempPath();
        }
        var bf = new BrowserFetcher(bfOptions);
        bf.DownloadAsync(BrowserFetcher.DefaultRevision).Wait();
        var info = new AppInfo
        {
            BrowserExecutablePath = bf.GetExecutablePath(BrowserFetcher.DefaultRevision)
        };

        var port = GetAvailablePort();
        info.RazorPagesServerPort = port;
        builder.Services.AddSingleton(info);

        var webHost = Host.CreateDefaultBuilder()
            .ConfigureWebHostDefaults(webBuilder =>
            {
                var scriptRoot = Environment.GetEnvironmentVariable("AzureWebJobsScriptRoot");
                System.Console.WriteLine($"Starting web server on port {port}");
                if (!string.IsNullOrEmpty(scriptRoot))
                {
                    webBuilder.UseContentRoot(scriptRoot);
                }

                webBuilder.UseUrls($"http://0.0.0.0:{port}")
                    .UseStartup<RazorPagesApp.Startup>();
            })
            .Build();

        webHost.Start();
    }

    private int GetAvailablePort()
    {
        // 
        var listener = new TcpListener(IPAddress.Loopback, 0);
        listener.Start();
        int availablePort = ((IPEndPoint)listener.LocalEndpoint).Port;
        listener.Stop();
        return availablePort;
    }
}

public class AppInfo
{
    public string BrowserExecutablePath { get; set; }
    public int RazorPagesServerPort { get; set; }
}

根据文档,您有 ScreenShotDataAsync 其中 returns a byte[]:

byte[] data = await page.ScreenshotDataAsync(scrOpts);

还有 ScreenshotStreamAsync 其中 returns 一个 Stream:

Stream stream = await page.ScreenshotStreamAsync(scrOpts);