public async Task <byte[]> ConvertHtmlToPdf(string html, string cssPath) { var pdfOptions = new PdfOptions(); var browserFetcher = new BrowserFetcher(new BrowserFetcherOptions { Path = _chromiumPath }); await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision); using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { ExecutablePath = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision).ExecutablePath, Headless = true }); var page = await browser.NewPageAsync(); await page.SetContentAsync(html); await page.AddStyleTagAsync(new AddTagOptions { Path = cssPath }); var stream = await page.PdfStreamAsync(pdfOptions); using var ms = new MemoryStream(); await stream.CopyToAsync(ms); return(ms.ToArray()); }
static PicGen() { var downloadsFolder = Path.GetTempPath(); var option = new BrowserFetcherOptions { Path = downloadsFolder }; var fetcher = new BrowserFetcher(option); fetcher.DownloadAsync(BrowserFetcher.DefaultRevision).Wait(); var browser = Puppeteer.LaunchAsync(new LaunchOptions { ExecutablePath = fetcher.RevisionInfo(BrowserFetcher.DefaultRevision).ExecutablePath, Headless = true, Args = new[] { !isProd ? "--proxy-server=winip:1080" : "" } }).Result; page = browser.NewPageAsync().Result; page.SetViewportAsync(new ViewPortOptions { Height = 800, Width = 1300 }).Wait(); }
/// <summary> /// <para>设置一个 Chromium 浏览器 启动选项 的对象,并返回这个对象;此方法兼容 Windows7 / Windows Server 2008</para> /// <para>异常可能:程序运行目录下 Chromium 浏览器不可用。</para> /// </summary> /// <param name="checkIsDownload">检查 是否下载 Chromium 浏览器;默认 false</param> /// <param name="isDisplay">Chromium 运行时 是否显示界面;默认 true</param> /// <param name="args">要传递给 Chromium 浏览器实例的其他参数。( 此方法会自动传入 "--no-sandbox" 参数 ) /// <para>参考:https://peter.sh/experiments/chromium-command-line-switches/#no-sandbox </para> /// </param> /// <param name="ignoredDefaultArgs">如果给出数组,则过滤掉给定的 Puppeteer.DefaultArgs 默认参数。 /// ( 此方法会自动设置 "--enable-automation" 过滤掉这个参数 ) /// <para>参考:https://peter.sh/experiments/chromium-command-line-switches/#no-sandbox </para> /// </param> /// <returns></returns> private static async Task <LaunchOptions> SetChromiumLaunchOptions( bool checkIsDownload = false, bool isDisplay = true, string[] args = null, string[] ignoredDefaultArgs = null) { return(await Task.Run(async() => { BrowserFetcher browserFetcher = Puppeteer.CreateBrowserFetcher(new BrowserFetcherOptions()); RevisionInfo revisionInfo = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision); #region 检查下载 Chromium if (!(revisionInfo.Downloaded && revisionInfo.Local)) { if (checkIsDownload) { #region 载地址 解析;参考于源代码:https://github.com/hardkoded/puppeteer-sharp/blob/37ea56934281209830254df3ec3ffe37c57cfac2/lib/PuppeteerSharp/BrowserFetcher.cs // https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/706915/chrome-win.zip 下载地址( 样例 ) // const string DefaultDownloadHost = "https://storage.googleapis.com"; // const int DefaultRevision = 706915; // [Platform.Linux] = "{0}/chromium-browser-snapshots/Linux_x64/{1}/{2}.zip", // [Platform.MacOS] = "{0}/chromium-browser-snapshots/Mac/{1}/{2}.zip", // [Platform.Win32] = "{0}/chromium-browser-snapshots/Win/{1}/{2}.zip", // [Platform.Win64] = "{0}/chromium-browser-snapshots/Win_x64/{1}/{2}.zip" // case Platform.Linux: // return "chrome-linux"; // case Platform.MacOS: // return "chrome-mac"; // case Platform.Win32: // case Platform.Win64: // return revision > 591479 ? "chrome-win" : "chrome-win32"; #endregion // 检查 revisionInfo.Revision 这个版本的 Chromium 浏览器 是否 可下载 bool isCan = await browserFetcher.CanDownloadAsync(revisionInfo.Revision); if (isCan) { // 下载 revisionInfo.Revision 这个版本的无头浏览器;可能需要等待一些时间 await browserFetcher.DownloadAsync(revisionInfo.Revision); } else { throw new Exception($"程序检测出 Chromium 浏览器(默认版本 {revisionInfo.Revision})无法更新!"); } } else { throw new Exception("程序运行目录下 Chromium 浏览器不可用。请开发人员检查 程序运行目录下 是否正确安装 Chromium 浏览器。"); } } #endregion #region 兼容 Windows7 / Windows Server 2008 LaunchOptions launchOptions = default(LaunchOptions); // 这个判断是为了兼容 Windows7 和 Windows Server 2008 if (OSHelper.IsWin7Under()) { launchOptions = new LaunchOptions { WebSocketFactory = async(uri, socketOptions, cancellationToken) => { WebSocket client = SystemClientWebSocket.CreateClientWebSocket(); if (client is System.Net.WebSockets.Managed.ClientWebSocket managed) { managed.Options.KeepAliveInterval = TimeSpan.FromSeconds(0); await managed.ConnectAsync(uri, cancellationToken); } else { ClientWebSocket coreSocket = client as ClientWebSocket; coreSocket.Options.KeepAliveInterval = TimeSpan.FromSeconds(0); await coreSocket.ConnectAsync(uri, cancellationToken); } return client; } }; } else { launchOptions = new LaunchOptions(); } #endregion #region 设置 Args 参数 string[] argss = default(string[]); if (args != null && args.Length > 0) { List <string> argsList = args.ToList <string>(); argsList.Add("--no-sandbox"); argss = argsList.ToArray(); } else { argss = new string[] { "--no-sandbox" }; } launchOptions.Args = argss; //这些参数将会传递给 Chromium #endregion #region 设置 IgnoredDefaultArgs 参数 string[] defaultArgs = default(string[]); if (ignoredDefaultArgs != null && ignoredDefaultArgs.Length > 0) { List <string> ignoredDefaultArgsList = ignoredDefaultArgs.ToList <string>(); ignoredDefaultArgsList.Add("--enable-automation"); defaultArgs = ignoredDefaultArgsList.ToArray(); } else { defaultArgs = new string[] { "--enable-automation" }; } launchOptions.IgnoredDefaultArgs = defaultArgs; //这些参数将被 Chromium 忽略 #endregion launchOptions.Headless = !isDisplay; // Headless : true 是无头模式,无界面;false,有界面 return launchOptions; })); }
public static RevisionInfo RevisionInfo(int revision) { return(BrowserFetcher.RevisionInfo(revision != 0 ? revision : BrowserFetcher.DefaultRevision)); }
/// <summary> /// <para>设置一个 Chromium 浏览器 启动选项 的对象,并返回这个对象;此方法兼容 Windows7 / Windows Server 2008</para> /// <para>异常可能:程序运行目录下 Chromium 浏览器不可用。</para> /// </summary> /// <param name="checkIsDownload">检查 是否下载 Chromium 浏览器;默认 false</param> /// <param name="isDisplay">Chromium 运行时 是否显示界面;默认 true</param> /// <param name="args">要传递给 Chromium 浏览器实例的其他参数。( 此方法会自动传入 "--no-sandbox" 参数 ) /// <para>参考:https://peter.sh/experiments/chromium-command-line-switches/#no-sandbox </para> /// </param> /// <param name="ignoredDefaultArgs">如果给出数组,则过滤掉给定的 Puppeteer.DefaultArgs 默认参数。 /// ( 此方法会自动设置 "--enable-automation" 过滤掉这个参数 ) /// <para>参考:https://peter.sh/experiments/chromium-command-line-switches/#no-sandbox </para> /// </param> /// <returns></returns> private static async Task <LaunchOptions> SetChromiumLaunchOptions( bool checkIsDownload = false, bool isDisplay = true, string[] args = null, string[] ignoredDefaultArgs = null) { return(await Task.Run(async() => { BrowserFetcher browserFetcher = Puppeteer.CreateBrowserFetcher(new BrowserFetcherOptions()); RevisionInfo revisionInfo = browserFetcher.RevisionInfo(BrowserFetcher.DefaultChromiumRevision); #region 检查下载 Chromium if (!(revisionInfo.Downloaded && revisionInfo.Local)) { if (checkIsDownload) { // 检查 revisionInfo.Revision 这个版本的 Chromium 浏览器 是否 可下载 bool isCan = await browserFetcher.CanDownloadAsync(revisionInfo.Revision); if (isCan) { // 下载 revisionInfo.Revision 这个版本的无头浏览器;可能需要等待一些时间 await browserFetcher.DownloadAsync(revisionInfo.Revision); } else { throw new Exception($"程序检测出 Chromium 浏览器(默认版本 {revisionInfo.Revision})无法更新!"); } } else { throw new Exception("程序运行目录下 Chromium 浏览器不可用。请开发人员检查 程序运行目录下 是否正确安装 Chromium 浏览器。"); } } #endregion #region 兼容 Windows7 / Windows Server 2008 LaunchOptions launchOptions = default(LaunchOptions); // 这个判断是为了兼容 Windows7 和 Windows Server 2008 if (OSHelper.IsWin7Under()) { launchOptions = new LaunchOptions { WebSocketFactory = async(uri, socketOptions, cancellationToken) => { WebSocket client = SystemClientWebSocket.CreateClientWebSocket(); if (client is System.Net.WebSockets.Managed.ClientWebSocket managed) { managed.Options.KeepAliveInterval = TimeSpan.FromSeconds(0); await managed.ConnectAsync(uri, cancellationToken); } else { ClientWebSocket coreSocket = client as ClientWebSocket; coreSocket.Options.KeepAliveInterval = TimeSpan.FromSeconds(0); await coreSocket.ConnectAsync(uri, cancellationToken); } return client; } }; } else { launchOptions = new LaunchOptions(); } #endregion #region 设置 Args 参数 string[] argss = default(string[]); if (args != null && args.Length > 0) { List <string> argsList = args.ToList <string>(); argsList.Add("--no-sandbox"); argss = argsList.ToArray(); } else { argss = new string[] { "--no-sandbox" }; } launchOptions.Args = argss; // 这些参数将会传递给 Chromium #endregion #region 设置 IgnoredDefaultArgs 参数 string[] defaultArgs = default(string[]); if (ignoredDefaultArgs != null && ignoredDefaultArgs.Length > 0) { List <string> ignoredDefaultArgsList = ignoredDefaultArgs.ToList <string>(); ignoredDefaultArgsList.Add("--enable-automation"); defaultArgs = ignoredDefaultArgsList.ToArray(); } else { defaultArgs = new string[] { "--enable-automation" }; } launchOptions.IgnoredDefaultArgs = defaultArgs; // 这些参数将被 Chromium 忽略 #endregion launchOptions.Headless = !isDisplay; // Headless : true 是无头模式,无界面;false,有界面 return launchOptions; })); }
private async Task <RevisionInfo> EnsureDownloadsAsync() { var browserFetcher = new BrowserFetcher(new BrowserFetcherOptions { Path = GetDownloadsDirectory(), }); var desiredRevision = BrowserFetcher.DefaultRevision; var revisionInfo = browserFetcher.RevisionInfo(desiredRevision); if (revisionInfo.Downloaded && revisionInfo.Local) { _logger.LogDebug( "Using Chromium revision {Revision} for {Platform}.", revisionInfo.Revision, revisionInfo.Platform); } else { _logger.LogInformation( $"Downloading Chromium revision {{Revision}} for {{Platform}} to:{Environment.NewLine}{{FolderPath}}", revisionInfo.Revision, revisionInfo.Platform, revisionInfo.FolderPath); // Set up the progress report. long?contentLength; using (var httpClient = new HttpClient()) using (var request = new HttpRequestMessage(HttpMethod.Head, revisionInfo.Url)) using (var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead)) { contentLength = response.Content.Headers.ContentLength; } long progressIncrement; if (contentLength.HasValue) { _logger.LogDebug("The download will be {Bytes:N0} bytes.", contentLength); // 5% progressIncrement = 5; } else { // 1 megabyte progressIncrement = 1024 * 1024; } long nextProgress = 0; var progressLock = new object(); browserFetcher.DownloadProgressChanged += (sender, e) => { lock (progressLock) { if (contentLength.HasValue) { var progressPercentage = (int)Math.Round((100.0 * e.BytesReceived) / contentLength.Value); if (progressPercentage > nextProgress) { _logger.LogInformation("Download progress: {Percentage}%", progressPercentage); nextProgress += progressIncrement; } } else { if (e.BytesReceived > nextProgress) { _logger.LogInformation("Download progress: {BytesReceived:N0} bytes", e.BytesReceived); nextProgress += progressIncrement; } } } }; // Start the download. revisionInfo = await browserFetcher.DownloadAsync(desiredRevision); if (contentLength.HasValue) { _logger.LogInformation("Download progress: {Percentage}%", 100); } _logger.LogInformation("Chromium is done downloading."); } return(revisionInfo); }
// 无头浏览器测试 private void btn_chromiumTest_Click(object sender, EventArgs e) { this.Invoke(new Action(() => { this.btn_chromiumTest.Enabled = false; this.rTxt_log.Clear(); })); Task.Run(async() => { #region 无头浏览器下载更新 BrowserFetcher browserFetcher = Puppeteer.CreateBrowserFetcher(new BrowserFetcherOptions()); RevisionInfo revisionInfo = browserFetcher.RevisionInfo(BrowserFetcher.DefaultChromiumRevision); if (revisionInfo.Downloaded && revisionInfo.Local) { this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器检查完成,无需更新! \n"); })); } else { this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器检查完成,需要更新! \n"); this.rTxt_log.AppendText("正在检查更新... \n"); })); // 检查 revisionInfo.Revision 这个版本的 Chromium 浏览器 是否 可下载 bool isCan = await browserFetcher.CanDownloadAsync(revisionInfo.Revision); if (!isCan) { this.Invoke(new Action(() => { this.rTxt_log.AppendText($"程序检测出无头浏览器(默认版本 {revisionInfo.Revision})无法更新! \n"); this.btn_chromiumTest.Enabled = true; })); return; } this.Invoke(new Action(() => { this.rTxt_log.AppendText("正在更新无头浏览器... \n"); })); // 下载 revisionInfo.Revision 这个版本的无头浏览器;可能需要等待一些时间 await browserFetcher.DownloadAsync(revisionInfo.Revision); this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器更新完成。 \n"); })); } #endregion this.Invoke(new Action(() => { this.rTxt_log.AppendText("开始测试无头浏览器... \n"); })); await TestHeadlessChromiumAsync(); this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器测试完成。 \n"); this.btn_chromiumTest.Enabled = true; })); }); }
// 无头浏览器测试 private void btn_chromiumTest_Click(object sender, EventArgs e) { this.Invoke(new Action(() => { this.btn_chromiumTest.Enabled = false; this.rTxt_log.Clear(); })); Task.Run(async() => { #region 无头浏览器下载更新 BrowserFetcher browserFetcher = Puppeteer.CreateBrowserFetcher(new BrowserFetcherOptions()); RevisionInfo revisionInfo = browserFetcher.RevisionInfo(BrowserFetcher.DefaultRevision); #region 载地址 解析;参考于源代码:https://github.com/hardkoded/puppeteer-sharp/blob/37ea56934281209830254df3ec3ffe37c57cfac2/lib/PuppeteerSharp/BrowserFetcher.cs // https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/706915/chrome-win.zip 下载地址( 样例 ) // const string DefaultDownloadHost = "https://storage.googleapis.com"; // const int DefaultRevision = 706915; // [Platform.Linux] = "{0}/chromium-browser-snapshots/Linux_x64/{1}/{2}.zip", // [Platform.MacOS] = "{0}/chromium-browser-snapshots/Mac/{1}/{2}.zip", // [Platform.Win32] = "{0}/chromium-browser-snapshots/Win/{1}/{2}.zip", // [Platform.Win64] = "{0}/chromium-browser-snapshots/Win_x64/{1}/{2}.zip" // case Platform.Linux: // return "chrome-linux"; // case Platform.MacOS: // return "chrome-mac"; // case Platform.Win32: // case Platform.Win64: // return revision > 591479 ? "chrome-win" : "chrome-win32"; #endregion if (revisionInfo.Downloaded && revisionInfo.Local) { this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器检查完成,无需更新! \n"); })); } else { this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器检查完成,需要更新! \n"); this.rTxt_log.AppendText("正在检查更新... \n"); })); // 检查 revisionInfo.Revision 这个版本的 Chromium 浏览器 是否 可用\可下载 bool isCan = await browserFetcher.CanDownloadAsync(revisionInfo.Revision); if (!isCan) { this.Invoke(new Action(() => { this.rTxt_log.AppendText($"程序检测出无头浏览器(默认版本 {revisionInfo.Revision})无法更新! \n"); this.btn_chromiumTest.Enabled = true; })); return; } this.Invoke(new Action(() => { this.rTxt_log.AppendText("正在更新无头浏览器... \n"); })); // 下载 revisionInfo.Revision 这个版本的无头浏览器;可能需要等待一些时间 await browserFetcher.DownloadAsync(revisionInfo.Revision); this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器更新完成。 \n"); })); } #endregion this.Invoke(new Action(() => { this.rTxt_log.AppendText("开始测试无头浏览器... \n"); })); await TestHeadlessChromiumAsync(); this.Invoke(new Action(() => { this.rTxt_log.AppendText("无头浏览器测试完成。 \n"); this.btn_chromiumTest.Enabled = true; })); }); }