I have an cross platform library (.net framework 4.6.2, .net standard 2.0 and uwp). I've created a progressable stream content for uploading purpose.
In .net framework and .net standard everything is working perfectly but in UWP is not.
In uwp everytime, it will returns 500 server error (internal)
.
When I'm trying to upload without ProgressableStreamContent
everything is working well in UWP.
here is my class:
internal class ProgressableStreamContent : HttpContent
{
private const int defaultBufferSize = 100 * 1024;
private HttpContent content;
private readonly int _bufferSize;
public UploadProgress UploaderProgress { get; internal set; }
private readonly Action<UploadProgress> progress;
public ProgressableStreamContent(HttpContent content, Action<UploadProgress> progress) : this(content, defaultBufferSize, progress) { }
public ProgressableStreamContent(HttpContent content, int bufferSize, Action<UploadProgress> progress)
{
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException("bufferSize");
this.content = content ?? throw new ArgumentNullException("content");
if (bufferSize < 5120)
bufferSize = defaultBufferSize;
_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 uploadedBytes = 0;
using (var inputStream = await content.ReadAsStreamAsync())
{
while (true)
{
var length = await inputStream.ReadAsync(buffer, 0, buffer.Length);
if (length <= 0) break;
uploadedBytes += length;
Invoke(uploadedBytes, size);
await stream.WriteAsync(buffer, 0, length);
await stream.FlushAsync();
}
}
await stream.FlushAsync();
});
}
void Invoke(long bytes, long size)
{
if (UploaderProgress == null)
UploaderProgress = new UploadProgress();
UploaderProgress.FileSize = size;
UploaderProgress.UploadState = size == bytes ? UploadState.Uploaded : UploadState.Uploading;
UploaderProgress.UploadedBytes = bytes;
progress?.Invoke(UploaderProgress);
}
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);
}
}
And, how do I use it:
using (var client = new HttpClient())
{
var requestContent = new MultipartFormDataContent("UPLOAD ID");
byte[] fileBytes = null;// some image
var imgCnt = new ByteArrayContent(fileBytes);
imgCnt.Headers.Add("Content-Transfer-Encoding", "binary");
imgCnt.Headers.Add("Content-Type", "application/octet-stream");
var progressContent = new ProgressableStreamContent(imgCnt, 1024, progress);
requestContent.Add(progressContent, "photo", $"{Path.GetRandomFileName()}.jpg");
var req = await client.PostAsync(new Uri("SOME URI"), requestContent);
}
The code below should work. Seems you used incorrect parameters
using (var client = new HttpClient())
{
var requestContent = new MultipartFormDataContent("UPLOAD ID");
byte[] fileBytes = null;// some image
var imgCnt = new ByteArrayContent(fileBytes);
imgCnt.Headers.Add("Content-Transfer-Encoding", "binary");
imgCnt.Headers.Add("Content-Type", "application/octet-stream");
requestContent.Add(imgCnt, "photo", $"{Path.GetRandomFileName()}.jpg");
var progressContent = new ProgressableStreamContent(requestContent, 1024, progress);
var req = await client.PostAsync(new Uri("SOME URI"), progressContent);
}