本章讲述:C# 使用 HttpClient 和 FileStream 下载文件的方法
为了实现一个支持暂停、继续和取消功能的文件下载器,我们可以使用 HttpClient 和 FileStream 来处理文件下载。同时,我们可以通过控制台输入来管理这些操作。
以下是一个完整的示例代码:使用 ReadAsStreamAsync,在读取内容时先将其转换为流,然后再读取流中的数据。这样可以避免直接在 await 后面使用表达式(while ((bytesRead = await response.Content.ReadAsByteArrayAsync(buffer)) > 0)),出现CS1503错误。
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
namespace FileDownloaderApp
{
class Program
{
static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
static bool isDownloading = false;
static async void DownloadFile(string url, string savePath)
{
isDownloading = true;
using (HttpClient client = new HttpClient())
{
// 获取文件大小
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
long totalBytesToWrite = response.Content.Headers.ContentLength ?? 0;
if (totalBytesToWrite == 0)
{
Console.WriteLine("无法获取文件大小。");
return;
}
// 创建保存文件的流
using (FileStream fileStream = new FileStream(savePath, FileMode.Create))
{
byte[] buffer = new byte[1024 * 64]; // 缓冲区大小,可以根据需要调整
long totalBytesWritten = 0;
using (var stream = await response.Content.ReadAsStreamAsync())
{
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, bytesRead);
// 计算已下载的字节数
totalBytesWritten += bytesRead;
double progressPercentage = Math.Round((totalBytesWritten / (double)totalBytesToWrite) * 100, 2);
Console.Clear(); // 清除控制台内容
Console.WriteLine($"正在下载文件... {progressPercentage}% 完成");
if (cancellationTokenSource.Token.IsCancellationRequested)
{
Console.WriteLine("下载已取消。");
return;
}
await Task.Delay(10); // 简单的延时,避免CPU占用过高
if (progressPercentage >= 95)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("下载完成!");
Console.ResetColor();
isDownloading = false;
break;
}
}
}
}
}
}
static void Main(string[] args)
{
string url = "https://example.com/path/to/file.zip"; // 替换为实际的URL
string savePath = @"C:\path\to\save\file.zip"; // 替换为你希望保存的位置
Console.WriteLine("开始下载文件...");
DownloadFile(url, savePath);
while (isDownloading)
{
Console.WriteLine("\n请输入命令:");
Console.WriteLine("1. 暂停");
Console.WriteLine("2. 继续");
Console.WriteLine("3. 取消");
string input = Console.ReadLine();
switch (input)
{
case "1":
if (!cancellationTokenSource.Token.IsCancellationRequested)
{
cancellationTokenSource.Cancel();
Console.WriteLine("下载已暂停。");
}
break;
case "2":
if (cancellationTokenSource.Token.IsCancellationRequested)
{
cancellationTokenSource = new CancellationTokenSource();
isDownloading = true;
DownloadFile(url, savePath);
}
break;
case "3":
cancellationTokenSource.Cancel();
Console.WriteLine("下载已取消。");
isDownloading = false;
break;
}
if (cancellationTokenSource.Token.IsCancellationRequested)
{
Console.WriteLine("下载已取消,退出程序。");
break;
}
}
}
}
}
代码说明
获取文件大小:使用HttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)来获取文件的头部信息,从而确定文件总大小。
创建保存文件的流:使用FileStream来保存下载的内容到指定路径。
取消操作:通过CancellationTokenSource来支持暂停和继续下载。当用户请求取消时,会抛出OperationCanceledException。