C# HttpClient 突然停止下载
C# HttpClient Abruptly stops download
我有这个 C# 脚本,它应该从 GitHub 下载一个 zip 存档,解压它并将它放在一个特定的文件夹中:
using (var client = new HttpClient())
{
var filePath = Path.GetFullPath("runtime");@"https://github.com/BlackBirdTV/tank/releases/latest/download/runtime.zip?raw=true";
ConsoleUtilities.UpdateProgress("Downloading Runtime...", 0);
var request = await client.GetStreamAsync(url);
var buffer = new byte[(int)bufferSize];
var totalBytesRead = 0;
int bytes = 0;
while ((bytes = await request.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
totalBytesRead += bytes;
ConsoleUtilities.UpdateProgress($"Downloading Runtime... ({totalBytesRead} of {bufferSize} bytes read) ", (int)(totalBytesRead / bufferSize * 100));
}
}
Decompress(buffer, filePath);
当我现在运行这个时候,下载开始了,看起来好像已经完成了,但在一个零星的地方它只是停止了。不知何故,它下载了我的控制台显示的字节,但它们被清零了。似乎我的计算机接收到零(我对此表示怀疑)或者字节没有写入缓冲区。
奇怪的是,通过浏览器下载文件工作得很好。
非常感谢任何帮助
正如我在评论中所述,您的问题是 while 循环的每次迭代都会覆盖您的缓冲区,并且您没有在任何地方累积数据。所以你的最后一次迭代并没有完全填满缓冲区,你剩下的就是你在最后一次迭代中得到的任何数据。
您可以通过将累积的缓冲区存储在某处来修复该错误,但更好的解决方案是不要对缓冲区等大惊小怪,而只需使用 built-in CopyToAsync
方法 Stream
:
using var client = new HttpClient();
using var stream = await client.GetStreamAsync("https://github.com/BlackBirdTV/tank/releases/latest/download/runtime.zip?raw=true");
using var file = new FileStream(@"c:\temp\runtime.zip", FileMode.Create);
await stream.CopyToAsync(file);
这里我将其保存到位于 c:\temp\runtime.zip
的本地文件中,但显然要根据您的需要进行更改。我想你是在避免使用这种方法,这样你就可以跟踪进度,这很公平。因此,如果这对您来说真的很重要,请继续阅读以修复您的原始解决方案。
为了完整起见,这是通过将缓冲区写入 FileStream
:
修复的原始代码
var bufferSize = 1024 * 10;
var url = @"https://github.com/BlackBirdTV/tank/releases/latest/download/runtime.zip?raw=true";
using var client = new HttpClient();
using var stream = await client.GetStreamAsync(url);
using var file = new FileStream(@"c:\temp\runtime.zip", FileMode.Create);
var filePath = Path.GetFullPath("runtime");
var request = await client.GetStreamAsync(url);
var buffer = new byte[(int)bufferSize];
var totalBytesRead = 0;
int bytes = 0;
while ((bytes = await request.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await file.WriteAsync(buffer, 0, bytes);
totalBytesRead += bytes;
ConsoleUtilities.UpdateProgress($"Downloading Runtime... ({totalBytesRead} of {bufferSize} bytes read) ", (int)(totalBytesRead / bufferSize * 100));
}
我有这个 C# 脚本,它应该从 GitHub 下载一个 zip 存档,解压它并将它放在一个特定的文件夹中:
using (var client = new HttpClient())
{
var filePath = Path.GetFullPath("runtime");@"https://github.com/BlackBirdTV/tank/releases/latest/download/runtime.zip?raw=true";
ConsoleUtilities.UpdateProgress("Downloading Runtime...", 0);
var request = await client.GetStreamAsync(url);
var buffer = new byte[(int)bufferSize];
var totalBytesRead = 0;
int bytes = 0;
while ((bytes = await request.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
totalBytesRead += bytes;
ConsoleUtilities.UpdateProgress($"Downloading Runtime... ({totalBytesRead} of {bufferSize} bytes read) ", (int)(totalBytesRead / bufferSize * 100));
}
}
Decompress(buffer, filePath);
当我现在运行这个时候,下载开始了,看起来好像已经完成了,但在一个零星的地方它只是停止了。不知何故,它下载了我的控制台显示的字节,但它们被清零了。似乎我的计算机接收到零(我对此表示怀疑)或者字节没有写入缓冲区。
奇怪的是,通过浏览器下载文件工作得很好。
非常感谢任何帮助
正如我在评论中所述,您的问题是 while 循环的每次迭代都会覆盖您的缓冲区,并且您没有在任何地方累积数据。所以你的最后一次迭代并没有完全填满缓冲区,你剩下的就是你在最后一次迭代中得到的任何数据。
您可以通过将累积的缓冲区存储在某处来修复该错误,但更好的解决方案是不要对缓冲区等大惊小怪,而只需使用 built-in CopyToAsync
方法 Stream
:
using var client = new HttpClient();
using var stream = await client.GetStreamAsync("https://github.com/BlackBirdTV/tank/releases/latest/download/runtime.zip?raw=true");
using var file = new FileStream(@"c:\temp\runtime.zip", FileMode.Create);
await stream.CopyToAsync(file);
这里我将其保存到位于 c:\temp\runtime.zip
的本地文件中,但显然要根据您的需要进行更改。我想你是在避免使用这种方法,这样你就可以跟踪进度,这很公平。因此,如果这对您来说真的很重要,请继续阅读以修复您的原始解决方案。
为了完整起见,这是通过将缓冲区写入 FileStream
:
var bufferSize = 1024 * 10;
var url = @"https://github.com/BlackBirdTV/tank/releases/latest/download/runtime.zip?raw=true";
using var client = new HttpClient();
using var stream = await client.GetStreamAsync(url);
using var file = new FileStream(@"c:\temp\runtime.zip", FileMode.Create);
var filePath = Path.GetFullPath("runtime");
var request = await client.GetStreamAsync(url);
var buffer = new byte[(int)bufferSize];
var totalBytesRead = 0;
int bytes = 0;
while ((bytes = await request.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await file.WriteAsync(buffer, 0, bytes);
totalBytesRead += bytes;
ConsoleUtilities.UpdateProgress($"Downloading Runtime... ({totalBytesRead} of {bufferSize} bytes read) ", (int)(totalBytesRead / bufferSize * 100));
}