Created
August 11, 2020 16:18
-
-
Save joncloud/400685b9501203e89abe26277e2d7333 to your computer and use it in GitHub Desktop.
Tracking stream progress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Azure.Storage.Blobs; | |
using System; | |
using System.IO; | |
using System.Threading; | |
using System.Threading.Tasks; | |
class Program | |
{ | |
static async Task Main(string[] args) | |
{ | |
BlobContainerClient container = default; | |
BlobClient blob = container.GetBlobClient("foo"); | |
var properties = await blob.GetPropertiesAsync(); | |
using var fileStream = File.Create("./blob"); | |
using var progressStream = new ProgressStream(fileStream); | |
progressStream.BytesRead += read => | |
{ | |
var percentage = read / (float)properties.Value.ContentLength; | |
}; | |
await blob.DownloadToAsync(progressStream); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ProgressStream : Stream | |
{ | |
readonly Stream _inner; | |
public ProgressStream(Stream inner) => | |
_inner = inner; | |
public override bool CanRead => _inner.CanRead; | |
public override bool CanSeek => _inner.CanSeek; | |
public override bool CanWrite => _inner.CanWrite; | |
public override long Length => _inner.Length; | |
public override long Position | |
{ | |
get => _inner.Position; | |
set => _inner.Position = value; | |
} | |
public override void Flush() => _inner.Flush(); | |
public override Task FlushAsync(CancellationToken cancellationToken) => _inner.FlushAsync(cancellationToken); | |
public event Action<int> BytesRead; | |
protected virtual void OnBytesRead(int read) | |
{ | |
if (read < 1) return; | |
BytesRead?.Invoke(read); | |
} | |
public override int Read(byte[] buffer, int offset, int count) | |
{ | |
var read = _inner.Read(buffer, offset, count); | |
OnBytesRead(read); | |
return read; | |
} | |
public override int Read(Span<byte> buffer) | |
{ | |
var read = _inner.Read(buffer); | |
OnBytesRead(read); | |
return read; | |
} | |
public override int ReadByte() | |
{ | |
var value = _inner.ReadByte(); | |
if (value > -1) | |
{ | |
OnBytesRead(1); | |
} | |
return value; | |
} | |
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |
{ | |
var read = await _inner.ReadAsync(buffer, offset, count, cancellationToken); | |
OnBytesRead(read); | |
return read; | |
} | |
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) | |
{ | |
var read = await _inner.ReadAsync(buffer, cancellationToken); | |
OnBytesRead(read); | |
return read; | |
} | |
public override long Seek(long offset, SeekOrigin origin) => | |
_inner.Seek(offset, origin); | |
public override void SetLength(long value) => | |
_inner.SetLength(value); | |
public event Action<int> BytesWritten; | |
protected virtual void OnBytesWritten(int written) | |
{ | |
if (written < 1) return; | |
BytesWritten?.Invoke(written); | |
} | |
public override void Write(byte[] buffer, int offset, int count) | |
{ | |
_inner.Write(buffer, offset, count); | |
OnBytesWritten(count); | |
} | |
public override void Write(ReadOnlySpan<byte> buffer) | |
{ | |
_inner.Write(buffer); | |
OnBytesWritten(buffer.Length); | |
} | |
public override void WriteByte(byte value) | |
{ | |
_inner.WriteByte(value); | |
OnBytesWritten(1); | |
} | |
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | |
{ | |
await _inner.WriteAsync(buffer, offset, count, cancellationToken); | |
OnBytesWritten(count); | |
} | |
public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) | |
{ | |
await _inner.WriteAsync(buffer, cancellationToken); | |
OnBytesWritten(buffer.Length); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment