【发布时间】:2021-08-24 08:24:31
【问题描述】:
我正在使用 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()
{
// https://stackoverflow.com/a/150974/9035640
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; }
}
【问题讨论】:
标签: c# puppeteer-sharp