上传时自定义 HttpContent 失败
Custom HttpContent fails while uploading
我有一个跨平台库(.net framework 4.6.2、.net standard 2.0 和 uwp)。
我已经创建了一个用于上传目的的进度流内容。
在 .net Framework 和 .net standard 中,一切都运行良好,但在 UWP 中则不然。
每次在 uwp 中,它都会 returns 500 server error (internal)
.
当我尝试在没有 ProgressableStreamContent
的情况下上传时,在 UWP 中一切正常。
这是我的 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);
}
}
以及,我该如何使用它:
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);
}
下面的代码应该可以工作。
似乎您使用了不正确的参数
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);
}
我有一个跨平台库(.net framework 4.6.2、.net standard 2.0 和 uwp)。 我已经创建了一个用于上传目的的进度流内容。
在 .net Framework 和 .net standard 中,一切都运行良好,但在 UWP 中则不然。
每次在 uwp 中,它都会 returns 500 server error (internal)
.
当我尝试在没有 ProgressableStreamContent
的情况下上传时,在 UWP 中一切正常。
这是我的 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);
}
}
以及,我该如何使用它:
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);
}
下面的代码应该可以工作。 似乎您使用了不正确的参数
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);
}