Skip to content

Commit c4b876a

Browse files
kblokMeir017
authored andcommitted
Allow screenshot to return a base64 string (#541)
* Allow screenshot to return a base64 string * Code Factor
1 parent e510b19 commit c4b876a

File tree

4 files changed

+59
-15
lines changed

4 files changed

+59
-15
lines changed

lib/PuppeteerSharp.Tests/PageTests/ScreenshotTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,23 @@ public async Task ShouldWorkWithOddClipSizeOnRetinaDisplays()
256256
}
257257
}
258258

259+
[Fact]
260+
public async Task ShouldReturnBase64()
261+
{
262+
using (var page = await Browser.NewPageAsync())
263+
{
264+
await page.SetViewportAsync(new ViewPortOptions
265+
{
266+
Width = 500,
267+
Height = 500
268+
});
269+
await page.GoToAsync(TestConstants.ServerUrl + "/grid.html");
270+
var screenshot = await page.ScreenshotBase64Async();
271+
272+
Assert.True(ScreenshotHelper.PixelMatch("screenshot-sanity.png", Convert.FromBase64String(screenshot)));
273+
}
274+
}
275+
259276
[Fact]
260277
public void ShouldInferScreenshotTypeFromName()
261278
{

lib/PuppeteerSharp/ElementHandle.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,22 @@ public async Task<Stream> ScreenshotStreamAsync(ScreenshotOptions options)
9898
/// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
9999
/// <param name="options">Screenshot options.</param>
100100
public async Task<byte[]> ScreenshotDataAsync(ScreenshotOptions options)
101+
=> Convert.FromBase64String(await ScreenshotBase64Async(options).ConfigureAwait(false));
102+
103+
/// <summary>
104+
/// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotBase64Async(ScreenshotOptions)"/> to take a screenshot of the element.
105+
/// If the element is detached from DOM, the method throws an error.
106+
/// </summary>
107+
/// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>
108+
public Task<string> ScreenshotBase64Async() => ScreenshotBase64Async(new ScreenshotOptions());
109+
110+
/// <summary>
111+
/// This method scrolls element into view if needed, and then uses <seealso cref="Page.ScreenshotBase64Async(ScreenshotOptions)"/> to take a screenshot of the element.
112+
/// If the element is detached from DOM, the method throws an error.
113+
/// </summary>
114+
/// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>
115+
/// <param name="options">Screenshot options.</param>
116+
public async Task<string> ScreenshotBase64Async(ScreenshotOptions options)
101117
{
102118
var needsViewportReset = false;
103119
var boundingBox = await AssertBoundingBoxAsync().ConfigureAwait(false);
@@ -126,7 +142,7 @@ await ExecutionContext.EvaluateFunctionAsync(@"function(element) {
126142
clip.Y += getLayoutMetricsResponse.LayoutViewport.PageY;
127143

128144
options.Clip = boundingBox.ToClip();
129-
var imageData = await Page.ScreenshotDataAsync(options).ConfigureAwait(false);
145+
var imageData = await Page.ScreenshotBase64Async(options).ConfigureAwait(false);
130146

131147
if (needsViewportReset)
132148
{

lib/PuppeteerSharp/Helpers/TaskQueue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace PuppeteerSharp.Helpers
66
{
77
internal class TaskQueue
88
{
9-
private SemaphoreSlim _semaphore;
9+
private readonly SemaphoreSlim _semaphore;
1010

1111
internal TaskQueue()
1212
{

lib/PuppeteerSharp/Page.cs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ private Page(CDPSession client, Target target, FrameTree frameTree, bool ignoreH
7878
_networkManager.Response += (sender, e) => Response?.Invoke(this, e);
7979
_networkManager.RequestFinished += (sender, e) => RequestFinished?.Invoke(this, e);
8080

81-
target.CloseTask.ContinueWith((arg) => {
81+
target.CloseTask.ContinueWith((arg) =>
82+
{
8283
Close?.Invoke(this, EventArgs.Empty);
8384
IsClosed = true;
8485
});
@@ -955,15 +956,15 @@ public async Task<Stream> ScreenshotStreamAsync(ScreenshotOptions options)
955956
/// <summary>
956957
/// Takes a screenshot of the page
957958
/// </summary>
958-
/// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
959-
public Task<byte[]> ScreenshotDataAsync() => ScreenshotDataAsync(new ScreenshotOptions());
959+
/// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>
960+
public Task<string> ScreenshotBase64Async() => ScreenshotBase64Async(new ScreenshotOptions());
960961

961962
/// <summary>
962963
/// Takes a screenshot of the page
963964
/// </summary>
964-
/// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
965+
/// <returns>Task which resolves to a <see cref="string"/> containing the image data as base64.</returns>
965966
/// <param name="options">Screenshot options.</param>
966-
public Task<byte[]> ScreenshotDataAsync(ScreenshotOptions options)
967+
public Task<string> ScreenshotBase64Async(ScreenshotOptions options)
967968
{
968969
var screenshotType = options.Type;
969970

@@ -993,6 +994,20 @@ public Task<byte[]> ScreenshotDataAsync(ScreenshotOptions options)
993994
return _screenshotTaskQueue.Enqueue(() => PerformScreenshot(screenshotType.Value, options));
994995
}
995996

997+
/// <summary>
998+
/// Takes a screenshot of the page
999+
/// </summary>
1000+
/// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
1001+
public Task<byte[]> ScreenshotDataAsync() => ScreenshotDataAsync(new ScreenshotOptions());
1002+
1003+
/// <summary>
1004+
/// Takes a screenshot of the page
1005+
/// </summary>
1006+
/// <returns>Task which resolves to a <see cref="byte"/>[] containing the image data.</returns>
1007+
/// <param name="options">Screenshot options.</param>
1008+
public async Task<byte[]> ScreenshotDataAsync(ScreenshotOptions options)
1009+
=> Convert.FromBase64String(await ScreenshotBase64Async(options).ConfigureAwait(false));
1010+
9961011
/// <summary>
9971012
/// Returns page's title
9981013
/// </summary>
@@ -1022,10 +1037,8 @@ public Task CloseAsync(PageCloseOptions options = null)
10221037
}).ContinueWith((task) => Target.CloseTask);
10231038
}
10241039
}
1025-
else
1026-
{
1027-
_logger.LogWarning("Protocol error: Connection closed. Most likely the page has been closed.");
1028-
}
1040+
1041+
_logger.LogWarning("Protocol error: Connection closed. Most likely the page has been closed.");
10291042
return Task.CompletedTask;
10301043
}
10311044

@@ -1457,7 +1470,7 @@ private Dictionary<string, decimal> BuildMetricsObject(List<Metric> metrics)
14571470
return result;
14581471
}
14591472

1460-
private async Task<byte[]> PerformScreenshot(ScreenshotType type, ScreenshotOptions options)
1473+
private async Task<string> PerformScreenshot(ScreenshotType type, ScreenshotOptions options)
14611474
{
14621475
await Client.SendAsync("Target.activateTarget", new
14631476
{
@@ -1551,9 +1564,7 @@ private async Task<byte[]> PerformScreenshot(ScreenshotType type, ScreenshotOpti
15511564
await SetViewportAsync(Viewport).ConfigureAwait(false);
15521565
}
15531566

1554-
var buffer = Convert.FromBase64String(result.GetValue("data").Value<string>());
1555-
1556-
return buffer;
1567+
return result.GetValue("data").Value<string>();
15571568
}
15581569

15591570
private decimal ConvertPrintParameterToInches(object parameter)

0 commit comments

Comments
 (0)