当存在多种内容类型时,在 DelegatingHandler 中读取 HttpContent 字节失败
Reading HttpContent bytes fails inside DelegatingHandler when multiple content types present
我正在尝试为 API 实施 HMAC 安全性。一切正常,直到我尝试将 post 数据值与 MultipartFormDataContent
.
中的文件一起使用
当命中读取字节的异步代码行时,HttpClient
DelegatingHandler
静默失败。
这是构建请求的代码:
private FileOutputViewModel GetApiOutput(Uri apiResource, string filename, byte[] file, IDictionary<string, string> extraParameters)
{
FileOutputViewModel result = new FileOutputViewModel();
if (file != null)
{
using (var content = new MultipartFormDataContent())
{
if (extraParameters != null)
{
foreach (var param in extraParameters)
{
content.Add(new StringContent(param.Value), param.Key); // <- If I don't have this, everything works fine
}
}
var fileContent = new ByteArrayContent(file);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = filename
};
content.Add(fileContent);
var response = HttpClient.PostAsync(apiResource.ToString(), content).Result;
result.Output = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
result.Filename = Path.GetFileName(filename);
}
}
return result;
}
如果我不使用 DelegatingHandler
一切正常,但 HMAC 安全性未针对请求实施,因此在 API 端被拒绝。
如果我不在文件旁边使用 StringContent
项添加数据值,那么读取字节就没有问题。但是我留下了一个不完整的请求,因为我需要随文件一起传递更多信息。
DelegatingHandler
中失败的代码行如下所示:
private static async Task<byte[]> ComputeHash(HttpContent httpContent)
{
using (var md5 = MD5.Create())
{
byte[] hash = null;
if (httpContent != null)
{
var ms = new MemoryStream();
await httpContent.CopyToAsync(ms); // <- Fails here
ms.Seek(0, SeekOrigin.Begin);
var content = ms.ToArray();
if (content.Length != 0)
{
hash = md5.ComputeHash(content);
}
}
return hash;
}
}
最初失败的行是:
var content = await httpContent.ReadAsByteArrayAsync();
但这失败了,即使只有文件本身(之前的 )。使用 MemoryStream
是向前迈出的一步,但并没有让我一路走来。
有什么办法可以解决这个问题吗?
这似乎是由 System.Net.Http.DelegatingHandler.SendAsync
方法的异步签名引起的。最初委托覆盖是:
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
当我调整代码以便将其更改为:
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
一切开始按预期工作。
似乎 .NET 框架的这一部分一定存在线程问题。如果您需要尝试其他解决方法,这里还介绍了一些其他解决方法:https://social.msdn.microsoft.com/Forums/vstudio/en-US/55f5571d-fe94-4b68-b1d4-bfb91fd721dd/reading-httpcontent-bytes-fails-inside-delegatinghandler-when-multiple-content-types-present?forum=wcf
我正在尝试为 API 实施 HMAC 安全性。一切正常,直到我尝试将 post 数据值与 MultipartFormDataContent
.
当命中读取字节的异步代码行时,HttpClient
DelegatingHandler
静默失败。
这是构建请求的代码:
private FileOutputViewModel GetApiOutput(Uri apiResource, string filename, byte[] file, IDictionary<string, string> extraParameters)
{
FileOutputViewModel result = new FileOutputViewModel();
if (file != null)
{
using (var content = new MultipartFormDataContent())
{
if (extraParameters != null)
{
foreach (var param in extraParameters)
{
content.Add(new StringContent(param.Value), param.Key); // <- If I don't have this, everything works fine
}
}
var fileContent = new ByteArrayContent(file);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = filename
};
content.Add(fileContent);
var response = HttpClient.PostAsync(apiResource.ToString(), content).Result;
result.Output = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
result.Filename = Path.GetFileName(filename);
}
}
return result;
}
如果我不使用 DelegatingHandler
一切正常,但 HMAC 安全性未针对请求实施,因此在 API 端被拒绝。
如果我不在文件旁边使用 StringContent
项添加数据值,那么读取字节就没有问题。但是我留下了一个不完整的请求,因为我需要随文件一起传递更多信息。
DelegatingHandler
中失败的代码行如下所示:
private static async Task<byte[]> ComputeHash(HttpContent httpContent)
{
using (var md5 = MD5.Create())
{
byte[] hash = null;
if (httpContent != null)
{
var ms = new MemoryStream();
await httpContent.CopyToAsync(ms); // <- Fails here
ms.Seek(0, SeekOrigin.Begin);
var content = ms.ToArray();
if (content.Length != 0)
{
hash = md5.ComputeHash(content);
}
}
return hash;
}
}
最初失败的行是:
var content = await httpContent.ReadAsByteArrayAsync();
但这失败了,即使只有文件本身(之前的 MemoryStream
是向前迈出的一步,但并没有让我一路走来。
有什么办法可以解决这个问题吗?
这似乎是由 System.Net.Http.DelegatingHandler.SendAsync
方法的异步签名引起的。最初委托覆盖是:
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
当我调整代码以便将其更改为:
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
一切开始按预期工作。
似乎 .NET 框架的这一部分一定存在线程问题。如果您需要尝试其他解决方法,这里还介绍了一些其他解决方法:https://social.msdn.microsoft.com/Forums/vstudio/en-US/55f5571d-fe94-4b68-b1d4-bfb91fd721dd/reading-httpcontent-bytes-fails-inside-delegatinghandler-when-multiple-content-types-present?forum=wcf