예제 #1
0
        /// <summary>
        /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotBase64Async(ScreenshotOptions)"/> to take a screenshot of the element.
        /// If the element is detached from DOM, the method throws an error.
        /// </summary>
        /// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>
        /// <param name="options">Screenshot options.</param>
        public async Task <string> ScreenshotBase64Async(ScreenshotOptions options)
        {
            var needsViewportReset = false;
            var boundingBox        = await BoundingBoxAsync().ConfigureAwait(false);

            if (boundingBox == null)
            {
                throw new PuppeteerException("Node is either not visible or not an HTMLElement");
            }

            var viewport = Page.Viewport;

            if (viewport != null && (boundingBox.Width > viewport.Width || boundingBox.Height > viewport.Height))
            {
                var newRawViewport = JObject.FromObject(viewport);
                newRawViewport.Merge(new ViewPortOptions
                {
                    Width  = (int)Math.Max(viewport.Width, Math.Ceiling(boundingBox.Width)),
                    Height = (int)Math.Max(viewport.Height, Math.Ceiling(boundingBox.Height))
                });
                await Page.SetViewportAsync(newRawViewport.ToObject <ViewPortOptions>()).ConfigureAwait(false);

                needsViewportReset = true;
            }
            await ExecutionContext.EvaluateFunctionAsync(@"function(element) {
                element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant'});
            }", this).ConfigureAwait(false);

            await ScrollIntoViewIfNeededAsync().ConfigureAwait(false);

            boundingBox = await BoundingBoxAsync().ConfigureAwait(false);

            if (boundingBox == null)
            {
                throw new PuppeteerException("Node is either not visible or not an HTMLElement");
            }
            var getLayoutMetricsResponse = await Client.SendAsync <GetLayoutMetricsResponse>("Page.getLayoutMetrics").ConfigureAwait(false);

            var clip = boundingBox;

            clip.X += getLayoutMetricsResponse.LayoutViewport.PageX;
            clip.Y += getLayoutMetricsResponse.LayoutViewport.PageY;

            options.Clip = boundingBox.ToClip();
            var imageData = await Page.ScreenshotBase64Async(options).ConfigureAwait(false);

            if (needsViewportReset)
            {
                await Page.SetViewportAsync(viewport).ConfigureAwait(false);
            }

            return(imageData);
        }
예제 #2
0
        /// <summary>
        /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
        /// If the element is detached from DOM, the method throws an error.
        /// </summary>
        /// <returns>The task</returns>
        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension.
        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided,
        /// the image won't be saved to the disk.</param>
        /// <param name="options">Screenshot options.</param>
        public async Task ScreenshotAsync(string file, ScreenshotOptions options)
        {
            var fileInfo = new FileInfo(file);

            options.Type = fileInfo.Extension.Replace(".", string.Empty);

            var data = await ScreenshotDataAsync(options);

            using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
            {
                await fs.WriteAsync(data, 0, data.Length);
            }
        }
예제 #3
0
        /// <summary>
        /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
        /// If the element is detached from DOM, the method throws an error.
        /// </summary>
        /// <returns>The task</returns>
        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension.
        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided,
        /// the image won't be saved to the disk.</param>
        /// <param name="options">Screenshot options.</param>
        public async Task ScreenshotAsync(string file, ScreenshotOptions options)
        {
            if (!options.Type.HasValue)
            {
                options.Type = ScreenshotOptions.GetScreenshotTypeFromFile(file);
            }

            var data = await ScreenshotDataAsync(options).ConfigureAwait(false);

            using (var fs = AsyncFileHelper.CreateStream(file, FileMode.Create))
            {
                await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
            }
        }
예제 #4
0
        /// <summary>
        /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
        /// If the element is detached from DOM, the method throws an error.
        /// </summary>
        /// <returns>The task</returns>
        /// <param name="file">The file path to save the image to. The screenshot type will be inferred from file extension.
        /// If path is a relative path, then it is resolved relative to current working directory. If no path is provided,
        /// the image won't be saved to the disk.</param>
        /// <param name="options">Screenshot options.</param>
        public async Task ScreenshotAsync(string file, ScreenshotOptions options)
        {
            if (!options.Type.HasValue)
            {
                options.Type = ScreenshotOptions.GetScreenshotTypeFromFile(file);
            }

            var data = await ScreenshotDataAsync(options);

            using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
            {
                await fs.WriteAsync(data, 0, data.Length);
            }
        }
예제 #5
0
        public async Task ScreenshotAsync(string file, ScreenshotOptions options)
        {
            var fileInfo = new FileInfo(file);

            options.Type = fileInfo.Extension.Replace(".", string.Empty);

            var stream = await ScreenshotStreamAsync(options);

            using (var fs = new FileStream(file, FileMode.Create, FileAccess.Write))
            {
                byte[] bytesInStream = new byte[stream.Length];
                stream.Read(bytesInStream, 0, bytesInStream.Length);
                fs.Write(bytesInStream, 0, bytesInStream.Length);
            }
        }
예제 #6
0
        /// <summary>
        /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotStreamAsync(ScreenshotOptions)"/> to take a screenshot of the element.
        /// If the element is detached from DOM, the method throws an error.
        /// </summary>
        /// <returns>The tas with the image streamk</returns>
        /// <param name="options">Screenshot options.</param>
        public async Task <Stream> ScreenshotStreamAsync(ScreenshotOptions options)
        {
            await ScrollIntoViewIfNeededAsync();

            dynamic metrics = await _client.SendAsync("Page.getLayoutMetrics") as JObject;

            var boundingBox = await BoundingBoxAsync();

            if (boundingBox == null)
            {
                throw new PuppeteerException("Node is not visible");
            }

            boundingBox.X += metrics.layoutViewport.pageX.ToObject <decimal>();
            boundingBox.Y += metrics.layoutViewport.pageY.ToObject <decimal>();
            options.Clip   = boundingBox.ToClip();
            return(await Page.ScreenshotStreamAsync(options));
        }
예제 #7
0
        /// <summary>
        /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
        /// If the element is detached from DOM, the method throws an error.
        /// </summary>
        /// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
        /// <param name="options">Screenshot options.</param>
        public async Task <byte[]> ScreenshotDataAsync(ScreenshotOptions options)
        {
            var needsViewportReset = false;
            var boundingBox        = await AssertBoundingBoxAsync();

            var viewport = Page.Viewport;

            if (boundingBox.Width > viewport.Width || boundingBox.Height > viewport.Height)
            {
                var newRawViewport = JObject.FromObject(viewport);
                newRawViewport.Merge(new ViewPortOptions
                {
                    Width  = (int)Math.Max(viewport.Width, Math.Ceiling(boundingBox.Width)),
                    Height = (int)Math.Max(viewport.Height, Math.Ceiling(boundingBox.Height))
                });
                await Page.SetViewportAsync(newRawViewport.ToObject <ViewPortOptions>());

                needsViewportReset = true;
            }
            await ExecutionContext.EvaluateFunctionAsync(@"function(element) {
                element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant'});
            }", this);

            boundingBox = await AssertBoundingBoxAsync();

            var getLayoutMetricsResponse = await Client.SendAsync <GetLayoutMetricsResponse>("Page.getLayoutMetrics");

            var clip = boundingBox;

            clip.X += getLayoutMetricsResponse.LayoutViewport.PageX;
            clip.Y += getLayoutMetricsResponse.LayoutViewport.PageY;

            options.Clip = boundingBox.ToClip();
            var imageData = await Page.ScreenshotDataAsync(options);

            if (needsViewportReset)
            {
                await Page.SetViewportAsync(viewport);
            }

            return(imageData);
        }
예제 #8
0
        public async Task <Stream> ScreenshotStreamAsync(ScreenshotOptions options)
        {
            string screenshotType = null;

            if (!string.IsNullOrEmpty(options.Type))
            {
                if (options.Type != "png" && options.Type != "jpeg")
                {
                    throw new ArgumentException($"Unknown options.type {options.Type}");
                }
                screenshotType = options.Type;
            }

            if (string.IsNullOrEmpty(screenshotType))
            {
                screenshotType = "png";
            }

            if (options.Quality.HasValue)
            {
                if (screenshotType == "jpeg")
                {
                    throw new ArgumentException($"options.Quality is unsupported for the {screenshotType} screenshots");
                }

                if (options.Quality < 0 || options.Quality > 100)
                {
                    throw new ArgumentException($"Expected options.quality to be between 0 and 100 (inclusive), got {options.Quality}");
                }
            }

            if (options.Clip != null && options.FullPage)
            {
                throw new ArgumentException("options.clip and options.fullPage are exclusive");
            }

            return(await _screenshotTaskQueue.Enqueue(() => PerformScreenshot(screenshotType, options)));
        }
예제 #9
0
 /// <summary>
 /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
 /// If the element is detached from DOM, the method throws an error.
 /// </summary>
 /// <returns>Task which resolves to a <see cref="Stream"/> containing the image data.</returns>
 /// <param name="options">Screenshot options.</param>
 public async Task <Stream> ScreenshotStreamAsync(ScreenshotOptions options)
 => new MemoryStream(await ScreenshotDataAsync(options).ConfigureAwait(false));
예제 #10
0
 /// <summary>
 /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
 /// If the element is detached from DOM, the method throws an error.
 /// </summary>
 /// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
 /// <param name="options">Screenshot options.</param>
 public async Task <byte[]> ScreenshotDataAsync(ScreenshotOptions options)
 => Convert.FromBase64String(await ScreenshotBase64Async(options).ConfigureAwait(false));
예제 #11
0
 /// <summary>
 /// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotDataAsync(ScreenshotOptions)"/> to take a screenshot of the element.
 /// If the element is detached from DOM, the method throws an error.
 /// </summary>
 /// <returns>Task which resolves to a <see cref="Stream"/> containing the image data.</returns>
 /// <param name="options">Screenshot options.</param>
 public async Task <Stream> ScreenshotStreamAsync(ScreenshotOptions options)
 => new MemoryStream(await ScreenshotDataAsync(options));
예제 #12
0
        public static async Task Main(string[] args)
        {
            var currentDirectory = Directory.GetCurrentDirectory();
            var downloadPath     = Path.Combine(currentDirectory, "CustomChromium");

            Console.WriteLine($"Attemping to set up puppeteer to use Chromium found under directory {downloadPath} ");

            if (!Directory.Exists(downloadPath))
            {
                Console.WriteLine("Custom directory not found. Creating directory");
                Directory.CreateDirectory(downloadPath);
            }

            Console.WriteLine("Downloading Chromium...");

            var browserFetcherOptions = new BrowserFetcherOptions {
                Path = downloadPath
            };
            var browserFetcher = new BrowserFetcher(browserFetcherOptions);
            await browserFetcher.DownloadAsync(BrowserFetcher.DefaultRevision);

            var executablePath = browserFetcher.GetExecutablePath(BrowserFetcher.DefaultRevision);

            if (string.IsNullOrEmpty(executablePath))
            {
                Console.WriteLine("Custom Chromium location is empty. Unable to start Chromium. Exiting.\n Press any key to continue");
                Console.ReadLine();
                return;
            }

            Console.WriteLine($"Attemping to start Chromium using executable path: {executablePath}");

            var options = new LaunchOptions {
                Headless = true, ExecutablePath = executablePath
            };

            using (var browser = await Puppeteer.LaunchAsync(options))
                using (var page = await browser.NewPageAsync())
                {
                    await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
                    await page.SetViewportAsync(new ViewPortOptions { Width = 1920, Height = 1080 });

                    var waitUntil = new NavigationOptions {
                        Timeout = 0, WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
                    };
                    string url = "https://github.com/puppeteer/puppeteer/issues/1345";
                    await page.GoToAsync(url, waitUntil);

                    #region Screenshot Dashboard:
                    var optionsScreenShot = new ScreenshotOptions {
                        FullPage = true
                    };
                    //Đường dẫn lưu file
                    var savePath = Path.Combine(currentDirectory, "Capture");
                    if (!Directory.Exists(savePath))
                    {
                        Console.WriteLine("SavePath directory not found. Creating directory");
                        Directory.CreateDirectory(savePath);
                    }
                    string date       = DateTime.Now.ToString("yyyyMMddHHmmss");
                    var    outputfile = savePath + "/capture_" + date + ".png";
                    await page.ScreenshotAsync(outputfile, optionsScreenShot);

                    Console.WriteLine("Capture completed! Path: " + outputfile, ConsoleColor.Green);
                    #endregion

                    await page.CloseAsync();
                }
            return;
        }
예제 #13
0
        private async Task <Stream> PerformScreenshot(string format, ScreenshotOptions options)
        {
            await _client.SendAsync("Target.activateTarget", new
            {
                targetId = _target.TargetId
            });

            var clip = options.Clip != null?options.Clip.Clone() : null;

            if (clip != null)
            {
                clip.Scale = 1;
            }

            if (options != null && options.FullPage)
            {
                dynamic metrics = await _client.SendAsync("Page.getLayoutMetrics");

                var width  = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(metrics.contentSize.width.Value)));
                var height = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(metrics.contentSize.height.Value)));

                // Overwrite clip for full page at all times.
                clip = new Clip
                {
                    X      = 0,
                    Y      = 0,
                    Width  = width,
                    Height = height,
                    Scale  = 1
                };

                var mobile            = _viewport.IsMobile;
                var deviceScaleFactor = _viewport.DeviceScaleFactor;
                var landscape         = _viewport.IsLandscape;
                var screenOrientation = landscape ?
                                        new ScreenOrientation
                {
                    Angle = 90,
                    Type  = ScreenOrientationType.LandscapePrimary
                } :
                new ScreenOrientation
                {
                    Angle = 0,
                    Type  = ScreenOrientationType.PortraitPrimary
                };

                await _client.SendAsync("Emulation.setDeviceMetricsOverride", new
                {
                    mobile,
                    width,
                    height,
                    deviceScaleFactor,
                    screenOrientation
                });
            }

            if (options != null && options.OmitBackground)
            {
                await _client.SendAsync("Emulation.setDefaultBackgroundColorOverride", new
                {
                    color = new
                    {
                        r = 0,
                        g = 0,
                        b = 0,
                        a = 0
                    }
                });
            }

            dynamic screenMessage = new ExpandoObject();

            screenMessage.format = format;

            if (options.Quality.HasValue)
            {
                screenMessage.quality = options.Quality.Value;
            }

            if (clip != null)
            {
                screenMessage.clip = clip;
            }

            JObject result = await _client.SendAsync("Page.captureScreenshot", screenMessage);

            if (options != null && options.OmitBackground)
            {
                await _client.SendAsync("Emulation.setDefaultBackgroundColorOverride");
            }

            if (options != null && options.FullPage)
            {
                await SetViewport(_viewport);
            }

            var buffer = Convert.FromBase64String(result.GetValue("data").Value <string>());

            return(new MemoryStream(buffer));
        }