Skip to content

Commit 90e965e

Browse files
authored
Move Path.PdfAsync to protocol streams (#1208)
* Move Path.PdfAsync to protocol streams * CodeFactor * Minor code change
1 parent acd7ad2 commit 90e965e

File tree

6 files changed

+104
-45
lines changed

6 files changed

+104
-45
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using PuppeteerSharp.Messaging;
8+
9+
namespace PuppeteerSharp.Helpers
10+
{
11+
internal static class ProtocolStreamReader
12+
{
13+
internal static async Task<string> ReadProtocolStreamStringAsync(CDPSession client, string handle, string path)
14+
{
15+
var result = new StringBuilder();
16+
var fs = !string.IsNullOrEmpty(path) ? AsyncFileHelper.CreateStream(path, FileMode.Create) : null;
17+
18+
try
19+
{
20+
var eof = false;
21+
22+
while (!eof)
23+
{
24+
var response = await client.SendAsync<IOReadResponse>("IO.read", new IOReadRequest
25+
{
26+
Handle = handle
27+
}).ConfigureAwait(false);
28+
29+
eof = response.Eof;
30+
31+
result.Append(response.Data);
32+
33+
if (fs != null)
34+
{
35+
var data = Encoding.UTF8.GetBytes(response.Data);
36+
await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
37+
}
38+
}
39+
40+
await client.SendAsync("IO.close", new IOCloseRequest
41+
{
42+
Handle = handle
43+
}).ConfigureAwait(false);
44+
45+
return result.ToString();
46+
}
47+
finally
48+
{
49+
fs?.Dispose();
50+
}
51+
}
52+
53+
internal static async Task<byte[]> ReadProtocolStreamByteAsync(CDPSession client, string handle, string path)
54+
{
55+
IEnumerable<byte> result = null;
56+
var eof = false;
57+
var fs = !string.IsNullOrEmpty(path) ? AsyncFileHelper.CreateStream(path, FileMode.Create) : null;
58+
59+
try
60+
{
61+
while (!eof)
62+
{
63+
var response = await client.SendAsync<IOReadResponse>("IO.read", new IOReadRequest
64+
{
65+
Handle = handle
66+
}).ConfigureAwait(false);
67+
68+
eof = response.Eof;
69+
var data = Convert.FromBase64String(response.Data);
70+
result = result == null ? data : result.Concat(data);
71+
72+
if (fs != null)
73+
{
74+
await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
75+
}
76+
}
77+
78+
await client.SendAsync("IO.close", new IOCloseRequest
79+
{
80+
Handle = handle
81+
}).ConfigureAwait(false);
82+
83+
return result.ToArray();
84+
}
85+
finally
86+
{
87+
fs?.Dispose();
88+
}
89+
}
90+
}
91+
}

lib/PuppeteerSharp/Messaging/IOReadResponse.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ internal class IOReadResponse
44
{
55
public bool Eof { get; set; }
66
public string Data { get; set; }
7+
public bool Base64Encoded { get; set; }
78
}
89
}

lib/PuppeteerSharp/Messaging/PagePrintToPDFRequest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ internal class PagePrintToPDFRequest
1616
public decimal MarginRight { get; set; }
1717
public string PageRanges { get; set; }
1818
public bool PreferCSSPageSize { get; set; }
19+
public string TransferMode { get; set; }
1920
}
2021
}

lib/PuppeteerSharp/Messaging/PagePrintToPDFResponse.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
internal class PagePrintToPDFResponse
44
{
55
public string Data { get; set; }
6+
public string Stream { get; set; }
67
}
78
}

lib/PuppeteerSharp/Page.cs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -855,14 +855,7 @@ public Task<Response> GoToAsync(string url, WaitUntilNavigation waitUntil)
855855
/// Generating a pdf is currently only supported in Chrome headless
856856
/// </remarks>
857857
public async Task PdfAsync(string file, PdfOptions options)
858-
{
859-
var data = await PdfDataAsync(options).ConfigureAwait(false);
860-
861-
using (var fs = AsyncFileHelper.CreateStream(file, FileMode.Create))
862-
{
863-
await fs.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
864-
}
865-
}
858+
=> await PdfInternalAsync(file, options).ConfigureAwait(false);
866859

867860
/// <summary>
868861
/// generates a pdf of the page with <see cref="MediaType.Print"/> css media. To generate a pdf with <see cref="MediaType.Screen"/> media call <see cref="EmulateMediaAsync(MediaType)"/> with <see cref="MediaType.Screen"/>
@@ -901,7 +894,9 @@ public async Task<Stream> PdfStreamAsync(PdfOptions options)
901894
/// <remarks>
902895
/// Generating a pdf is currently only supported in Chrome headless
903896
/// </remarks>
904-
public async Task<byte[]> PdfDataAsync(PdfOptions options)
897+
public Task<byte[]> PdfDataAsync(PdfOptions options) => PdfInternalAsync(null, options);
898+
899+
internal async Task<byte[]> PdfInternalAsync(string file, PdfOptions options)
905900
{
906901
var paperWidth = PaperFormat.Letter.Width;
907902
var paperHeight = PaperFormat.Letter.Height;
@@ -930,6 +925,7 @@ public async Task<byte[]> PdfDataAsync(PdfOptions options)
930925

931926
var result = await Client.SendAsync<PagePrintToPDFResponse>("Page.printToPDF", new PagePrintToPDFRequest
932927
{
928+
TransferMode = "ReturnAsStream",
933929
Landscape = options.Landscape,
934930
DisplayHeaderFooter = options.DisplayHeaderFooter,
935931
HeaderTemplate = options.HeaderTemplate,
@@ -946,7 +942,7 @@ public async Task<byte[]> PdfDataAsync(PdfOptions options)
946942
PreferCSSPageSize = options.PreferCSSPageSize
947943
}).ConfigureAwait(false);
948944

949-
return Convert.FromBase64String(result.Data);
945+
return await ProtocolStreamReader.ReadProtocolStreamByteAsync(Client, result.Stream, file).ConfigureAwait(false);
950946
}
951947

952948
/// <summary>

lib/PuppeteerSharp/Tracing.cs

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Text;
55
using System.Threading.Tasks;
66
using Microsoft.Extensions.Logging;
7+
using PuppeteerSharp.Helpers;
78
using PuppeteerSharp.Messaging;
89

910
namespace PuppeteerSharp
@@ -93,9 +94,10 @@ async void EventHandler(object sender, MessageEventArgs e)
9394
if (e.MessageID == "Tracing.tracingComplete")
9495
{
9596
var stream = e.MessageData.ToObject<TracingCompleteResponse>().Stream;
96-
var tracingData = await ReadStream(stream, _path).ConfigureAwait(false);
97+
var tracingData = await ProtocolStreamReader.ReadProtocolStreamStringAsync(_client, stream, _path).ConfigureAwait(false);
98+
9799
_client.MessageReceived -= EventHandler;
98-
taskWrapper.TrySetResult(tracingData);
100+
taskWrapper.TrySetResult(tracingData);
99101
}
100102
}
101103
catch (Exception ex)
@@ -114,38 +116,5 @@ async void EventHandler(object sender, MessageEventArgs e)
114116

115117
return await taskWrapper.Task.ConfigureAwait(false);
116118
}
117-
118-
private async Task<string> ReadStream(string stream, string path)
119-
{
120-
var result = new StringBuilder();
121-
var eof = false;
122-
123-
while (!eof)
124-
{
125-
var response = await _client.SendAsync<IOReadResponse>("IO.read", new IOReadRequest
126-
{
127-
Handle = stream
128-
}).ConfigureAwait(false);
129-
130-
eof = response.Eof;
131-
132-
result.Append(response.Data);
133-
}
134-
135-
if (!string.IsNullOrEmpty(path))
136-
{
137-
using (var fs = new StreamWriter(path))
138-
{
139-
await fs.WriteAsync(result.ToString()).ConfigureAwait(false);
140-
}
141-
}
142-
143-
await _client.SendAsync("IO.close", new IOCloseRequest
144-
{
145-
Handle = stream
146-
}).ConfigureAwait(false);
147-
148-
return result.ToString();
149-
}
150119
}
151120
}

0 commit comments

Comments
 (0)