在我的桌面应用程序中,我处理来自服务器的HTTP响应,我想提供相对于总响应长度的已处理字节的进度。
我知道HTTP标头中的内容长度,但是问题是对响应正文应用了压缩(gzip)。我可以计算已处理字节的数量,但是它们是在解压缩之后的,并且该数量与内容长度不同。 HTTP响应的Stream不可搜索,并且无法确定进度,因此我无法使用其Position
属性,因为我将拥有一个NotSupportedException
,类似于MSDN为NetworkStream.Position属性声明的内容。
下面是从压缩后的响应中读取的代码
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = httpClient.GetAsync(gzipGetUri, HttpCompletionOption.ResponseHeadersRead).Result;
long? contentLength = response.Content.Headers.ContentLength;
long totalCount = 0;
int percentDone = 0;
Stream responseStream = response.Content.ReadAsStreamAsync().Result;
Stream gzipStream = new GZipStream(responseStream, CompressionMode.Decompress);
byte[] buffer = new byte[1024];
while (true)
{
int nBytes = gzipStream.Read(buffer, 0, buffer.Length);
if (nBytes <= 0)
break;
// process decompressed bytes here...
totalCount += nBytes;
// This code throws NotSupportedException: This stream does not support seek operations
percentDone = (int)(((double)responseStream.Position / contentLength) * 100);
}
Console.WriteLine($"content-length: {contentLength}; bytes read from gzipStream: {totalCount}");
Console
的输出(当计算percentDone
的行被注释掉时)是
内容长度:1,316,578;从gzipStream读取的字节:9,410,402
我的问题是我如何确定在不可压缩的响应流中被解压缩之前所消耗的字节数。同样,我无法将解压缩后的计数用于percentDone
的计算,因为我不知道解压缩字节的最终数量。
我想我可以从Stream
派生一个类,该类计算通过字节的次数,将其用作responseStream
的包装器,并将其作为内部流传递给gzipStream
,但是该解决方案好像太重了