Skip to content

Instantly share code, notes, and snippets.

@scattered-code
Last active September 21, 2020 17:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scattered-code/e8c221058d63cfbce3dda867be4707bb to your computer and use it in GitHub Desktop.
Save scattered-code/e8c221058d63cfbce3dda867be4707bb to your computer and use it in GitHub Desktop.
// Source: https://forums.xamarin.com/discussion/180009/how-to-work-with-custom-progressable-stream-content
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace Misc
{
internal class ProgressableStreamContent : HttpContent
{
/// <summary>
/// Lets keep buffer of 20kb
/// </summary>
private const int defaultBufferSize = 5 * 4096;
private HttpContent content;
private int bufferSize;
private Action<long, long> progress;
public ProgressableStreamContent(HttpContent content, Action<long, long> progress) : this(content, defaultBufferSize, progress) { }
public ProgressableStreamContent(HttpContent content, int bufferSize, Action<long, long> progress)
{
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
this.content = content ?? throw new ArgumentNullException(nameof(content));
this.bufferSize = bufferSize;
this.progress = progress;
foreach (var h in content.Headers)
Headers.Add(h.Key, h.Value);
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return Task.Run(async () =>
{
var buffer = new byte[bufferSize];
TryComputeLength(out var size);
var uploaded = 0;
using (var sinput = await content.ReadAsStreamAsync())
{
while (true)
{
var length = sinput.Read(buffer, 0, buffer.Length);
if (length <= 0) break;
uploaded += length;
progress?.Invoke(uploaded, size);
stream.Write(buffer, 0, length);
stream.Flush();
}
}
stream.Flush();
});
}
protected override bool TryComputeLength(out long length)
{
length = content.Headers.ContentLength.GetValueOrDefault();
return true;
}
protected override void Dispose(bool disposing)
{
if (disposing)
content.Dispose();
base.Dispose(disposing);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment