当出现多个内容类型时,在DelegatingHandler内部读取HttpContent字节失败

本文关键字:内部 DelegatingHandler 读取 HttpContent 失败 字节 类型 | 更新日期: 2023-09-27 18:02:28

我正在尝试为API实现HMAC安全。一切都很好,直到我尝试在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();

,但这失败了,甚至只有文件本身(以前的Stackoverflow问题)。使用MemoryStream是向前迈进了一步,但还没有让我走完全程。

有什么办法可以解决这个问题吗?

当出现多个内容类型时,在DelegatingHandler内部读取HttpContent字节失败

似乎这是由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