首页 > 解决方案 > C# 的 HttpClient ReadAsStreamAsync

问题描述

我在使用 C# 的 HttpClient ReadAsStreamAsync 下载 400MB 以上的文件时遇到问题 - 问题是从 427724800 中仅读取了大约 213864187 个字节,然后

read = await stream.ReadAsync(buffer, 0, buffer.Length, token)

没有明显的原因一直返回 0。

有人有类似的问题吗?

using (var stream = await response.Content.ReadAsStreamAsync()) {
    var totalRead = 0L;
    var buffer = new byte[4096];                            
    var moreToRead = true;

    const int CHUNK_SIZE = 4096;
    var fileStream = File.Create(filename, CHUNK_SIZE);                            
    int bytesRead;
        do {
        token.ThrowIfCancellationRequested();

        var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);

        if (read == 0) {
            moreToRead = false;
            this.Percentage = 100;
            if (fileStream != null) {
                    fileStream.Close();
                    fileStream.Dispose();
                }
        } else {
            var data = new byte[read];
            buffer.ToList().CopyTo(0, data, 0, read);
            bytesRead = stream.Read(buffer, 0, CHUNK_SIZE);
            if (bytesRead > 0) {                                       
                fileStream.Write(buffer, 0, bytesRead);
            }                                    
            // Update the percentage of file downloaded
            totalRead += read;

            if (canReportProgress) {
                var downloadPercentage = ((totalRead * 1d) / (total * 1d)) * 100;
                var value = Convert.ToInt32(downloadPercentage);
                this.Percentage = value;
                this.BytesReceived = totalRead;
            }
        }
    }
    while (moreToRead);                           
}

标签: c#httpclient

解决方案


围绕这一点发生了一些奇怪的事情:

buffer.ToList().CopyTo(0, data, 0, read);
bytesRead = stream.Read(buffer, 0, CHUNK_SIZE);
if (bytesRead > 0) {                                       
    fileStream.Write(buffer, 0, bytesRead);
} 

我希望您将刚刚读到的字节单独写入fileStream- 即fileStream.Write(buffer, 0, read)。但是,您将缓冲区复制到一个data数组(不再使用),然后再次从流中读取这次buffer是同步的),然后写入.

所以你扔掉了一半的下载字节。难怪“仅从 427724800 中读取了大约 213864187 个字节”!

此外,using为您的 使用一个块fileStream,而不是使用显式.Dispose()调用。此外,如果您要将一个数组复制到另一个数组,请使用Array.Copy而不是array.ToList().CopyTo(...).


推荐阅读