CopyToAsync与ReadAsStreamAsync的巨大请求有效负载

时间:2018-07-31 07:42:52

标签: c# httpcontent

我必须为巨大的有效负载计算哈希,所以我使用流而不是将所有请求内容加载到内存中。问题是这段代码之间有什么区别:

using (var md5 = MD5.Create())
using (var stream = await authenticatableRequest.request.Content.ReadAsStreamAsync())
{
    return md5.ComputeHash(stream);
}

那一个:

using (var md5 = MD5.Create())  
using (var stream = new MemoryStream())
{
    await authenticatableRequest.request.Content.CopyToAsync(stream);
    stream.Position = 0;

    return md5.ComputeHash(stream);
}

我期望内部具有相同的行为,但也许我缺少一些东西。

3 个答案:

答案 0 :(得分:4)

第一个版本看起来不错,让哈希器处理流读取。它是为此目的而设计的。

ComputeHash(stream)将在while循环中读取块并重复调用TransformBlock()。

但是第二段代码 会将所有内容加载到内存中,所以不要这样做:

using (var stream = new MemoryStream())
{
    await authenticatableRequest.request.Content.CopyToAsync(stream);

答案 1 :(得分:2)

  

我希望内部具有相同的行为

为什么?我的意思是,在一种情况下,您必须将所有内容都加载到内存中(因为您猜出了什么,所以您定义了一个内存流)。在另一种情况下则不一定。

答案 2 :(得分:2)

第二个代码段不仅将所有内容加载到内存中,而且将使用比HttpContent.ReadAsByteArrayAsync()更多的内存。

MemoryStream是byte[] buffer上的Stream API,其初始大小为零。随着数据写入其中,缓冲区必须reallocated到缓冲区中,大小是原始缓冲区的两倍。这可以创建临时缓冲区对象的 lot ,其大小超过最终内容。

通过向capacity构造函数提供MemoryStream()参数,从一开始就分配最大的预期缓冲区大小,可以避免这种情况。

充其量,这类似于致电:

var bytes = authenticatableRequest.request.Content.ReadAsByteArrayAsync();
return md5.ComputeHash(bytes);