LANCommander/LANCommander.SDK/Extensions/StreamExtensions.cs
Pat Hartl c4217d7b41 Refactor HTTP streaming
Greatly reduces the amount of memory usage when streaming from the server by:
1. Shedding use of an internal MemoryStream
2. Using HttpCompletionOption.ResponseHeadersRead to start reading the stream without loading all of the HttpContent into memory
2025-10-09 02:16:20 -05:00

53 lines
No EOL
1.4 KiB
C#

using System;
using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace LANCommander.SDK.Extensions;
public static class StreamExtensions
{
public static async Task CopyToAsync(
this Stream source,
Stream destination,
Action<long, long> progressCallback = null,
CancellationToken cancellationToken = default,
int bufferSize = 1024 * 1024,
int reportIntervalBytes = 64 * 1024)
{
var buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
try
{
long transferred = 0;
long nextReportAt = reportIntervalBytes;
while (true)
{
int read = await source.ReadAsync(buffer.AsMemory(0, bufferSize), cancellationToken);
if (read == 0)
break;
await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken);
transferred += read;
if (transferred >= nextReportAt)
{
progressCallback?.Invoke(transferred, source.Length);
long multiples = transferred / nextReportAt;
nextReportAt = (multiples + 1) * reportIntervalBytes;
}
}
progressCallback?.Invoke(transferred, source.Length);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
}