c# - 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);
}
解决方案
围绕这一点发生了一些奇怪的事情:
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(...)
.
推荐阅读
- c# - XML 标记名称包括父类 ASP.NET
- javascript - 将 Nuxt 前端与 Flask 后端集成的最佳方法
- c# - 如何设置多对多关系,实体的不同关系状态可能会有所不同
- python - 将指定目录中的所有 .csv 文件导入单独的数组
- python - tf.keras.layers.pop() 不起作用,但 tf.keras._layers.pop() 起作用
- hyperledger - Hyperledger Iroha - 用例场景
- java - Vert.x IO Blocking 操作性能
- ios - SWRevealViewController 向呈现的视图控制器添加手势
- c - 将索引放在指针后面的 [] 括号内是什么意思?
- excel - Outlook Vba 在 Excel 宏中设置屏幕更新