@@ -24,6 +24,7 @@ internal class WebResponseContentMemoryStream : MemoryStream
24
24
{
25
25
#region Data
26
26
27
+ private readonly long ? _contentLength ;
27
28
private readonly Stream _originalStreamToProxy ;
28
29
private bool _isInitialized = false ;
29
30
private readonly Cmdlet _ownerCmdlet ;
@@ -37,9 +38,11 @@ internal class WebResponseContentMemoryStream : MemoryStream
37
38
/// <param name="stream"></param>
38
39
/// <param name="initialCapacity"></param>
39
40
/// <param name="cmdlet">Owner cmdlet if any.</param>
40
- internal WebResponseContentMemoryStream ( Stream stream , int initialCapacity , Cmdlet cmdlet )
41
+ /// <param name="contentLength">Expected download size in Bytes.</param>
42
+ internal WebResponseContentMemoryStream ( Stream stream , int initialCapacity , Cmdlet cmdlet , long ? contentLength )
41
43
: base ( initialCapacity )
42
44
{
45
+ this . _contentLength = contentLength ;
43
46
_originalStreamToProxy = stream ;
44
47
_ownerCmdlet = cmdlet ;
45
48
}
@@ -218,14 +221,24 @@ private void Initialize()
218
221
_isInitialized = true ;
219
222
try
220
223
{
221
- long totalLength = 0 ;
224
+ long totalRead = 0 ;
222
225
byte [ ] buffer = new byte [ StreamHelper . ChunkSize ] ;
223
226
ProgressRecord record = new ( StreamHelper . ActivityId , WebCmdletStrings . ReadResponseProgressActivity , "statusDescriptionPlaceholder" ) ;
224
- for ( int read = 1 ; read > 0 ; totalLength += read )
227
+ string totalDownloadSize = _contentLength is null ? "???" : Utils . DisplayHumanReadableFileSize ( ( long ) _contentLength ) ;
228
+ for ( int read = 1 ; read > 0 ; totalRead += read )
225
229
{
226
230
if ( _ownerCmdlet != null )
227
231
{
228
- record . StatusDescription = StringUtil . Format ( WebCmdletStrings . ReadResponseProgressStatus , totalLength ) ;
232
+ record . StatusDescription = StringUtil . Format (
233
+ WebCmdletStrings . ReadResponseProgressStatus ,
234
+ Utils . DisplayHumanReadableFileSize ( totalRead ) ,
235
+ totalDownloadSize ) ;
236
+
237
+ if ( _contentLength > 0 )
238
+ {
239
+ record . PercentComplete = Math . Min ( ( int ) ( totalRead * 100 / ( long ) _contentLength ) , 100 ) ;
240
+ }
241
+
229
242
_ownerCmdlet . WriteProgress ( record ) ;
230
243
231
244
if ( _ownerCmdlet . IsStopping )
@@ -244,13 +257,13 @@ private void Initialize()
244
257
245
258
if ( _ownerCmdlet != null )
246
259
{
247
- record . StatusDescription = StringUtil . Format ( WebCmdletStrings . ReadResponseComplete , totalLength ) ;
260
+ record . StatusDescription = StringUtil . Format ( WebCmdletStrings . ReadResponseComplete , totalRead ) ;
248
261
record . RecordType = ProgressRecordType . Completed ;
249
262
_ownerCmdlet . WriteProgress ( record ) ;
250
263
}
251
264
252
265
// make sure the length is set appropriately
253
- base . SetLength ( totalLength ) ;
266
+ base . SetLength ( totalRead ) ;
254
267
base . Seek ( 0 , SeekOrigin . Begin ) ;
255
268
}
256
269
catch ( Exception )
@@ -276,7 +289,7 @@ internal static class StreamHelper
276
289
277
290
#region Static Methods
278
291
279
- internal static void WriteToStream ( Stream input , Stream output , PSCmdlet cmdlet , CancellationToken cancellationToken )
292
+ internal static void WriteToStream ( Stream input , Stream output , PSCmdlet cmdlet , long ? contentLength , CancellationToken cancellationToken )
280
293
{
281
294
if ( cmdlet == null )
282
295
{
@@ -289,12 +302,22 @@ internal static void WriteToStream(Stream input, Stream output, PSCmdlet cmdlet,
289
302
ActivityId ,
290
303
WebCmdletStrings . WriteRequestProgressActivity ,
291
304
WebCmdletStrings . WriteRequestProgressStatus ) ;
305
+ string totalDownloadSize = contentLength is null ? "???" : Utils . DisplayHumanReadableFileSize ( ( long ) contentLength ) ;
292
306
293
307
try
294
308
{
295
309
while ( ! copyTask . Wait ( 1000 , cancellationToken ) )
296
310
{
297
- record . StatusDescription = StringUtil . Format ( WebCmdletStrings . WriteRequestProgressStatus , output . Position ) ;
311
+ record . StatusDescription = StringUtil . Format (
312
+ WebCmdletStrings . WriteRequestProgressStatus ,
313
+ Utils . DisplayHumanReadableFileSize ( output . Position ) ,
314
+ totalDownloadSize ) ;
315
+
316
+ if ( contentLength != null && contentLength > 0 )
317
+ {
318
+ record . PercentComplete = Math . Min ( ( int ) ( output . Position * 100 / ( long ) contentLength ) , 100 ) ;
319
+ }
320
+
298
321
cmdlet . WriteProgress ( record ) ;
299
322
}
300
323
@@ -316,13 +339,14 @@ internal static void WriteToStream(Stream input, Stream output, PSCmdlet cmdlet,
316
339
/// <param name="stream">Input stream.</param>
317
340
/// <param name="filePath">Output file name.</param>
318
341
/// <param name="cmdlet">Current cmdlet (Invoke-WebRequest or Invoke-RestMethod).</param>
342
+ /// <param name="contentLength">Expected download size in Bytes.</param>
319
343
/// <param name="cancellationToken">CancellationToken to track the cmdlet cancellation.</param>
320
- internal static void SaveStreamToFile ( Stream stream , string filePath , PSCmdlet cmdlet , CancellationToken cancellationToken )
344
+ internal static void SaveStreamToFile ( Stream stream , string filePath , PSCmdlet cmdlet , long ? contentLength , CancellationToken cancellationToken )
321
345
{
322
346
// If the web cmdlet should resume, append the file instead of overwriting.
323
347
FileMode fileMode = cmdlet is WebRequestPSCmdlet webCmdlet && webCmdlet . ShouldResume ? FileMode . Append : FileMode . Create ;
324
348
using FileStream output = new ( filePath , fileMode , FileAccess . Write , FileShare . Read ) ;
325
- WriteToStream ( stream , output , cmdlet , cancellationToken ) ;
349
+ WriteToStream ( stream , output , cmdlet , contentLength , cancellationToken ) ;
326
350
}
327
351
328
352
private static string StreamToString ( Stream stream , Encoding encoding )
0 commit comments