方法1:使用 HttpClient(异步,推荐)
csharp
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class FileDownloader
{
public static async Task DownloadFileAsync(string url, string localFilePath)
{
using (HttpClient httpClient = new HttpClient())
{
try
{
// 发送GET请求
HttpResponseMessage response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode(); // 确保响应成功
// 创建文件流
using (FileStream fileStream = new FileStream(localFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
// 将网络流复制到文件流
await response.Content.CopyToAsync(fileStream);
}
}
catch (Exception ex)
{
Console.WriteLine($"下载失败: {ex.Message}");
throw;
}
}
}
}
// 使用示例
await FileDownloader.DownloadFileAsync(
"https://example.com/files/document.pdf",
@"C:\Downloads\document.pdf"
);
方法2:使用 WebClient(同步/异步,旧版方法)
csharp
using System.Net;
// 异步版本
public static async Task DownloadWithWebClientAsync(string url, string savePath)
{
using (WebClient client = new WebClient())
{
await client.DownloadFileTaskAsync(new Uri(url), savePath);
}
}
// 同步版本(不推荐,会阻塞线程)
public static void DownloadWithWebClient(string url, string savePath)
{
using (WebClient client = new WebClient())
{
client.DownloadFile(url, savePath);
}
}
方法3:高级 HttpClient(支持进度报告)
csharp
public static async Task DownloadWithProgressAsync(string url, string savePath, IProgress<float> progress = null)
{
using (HttpClient httpClient = new HttpClient())
{
HttpResponseMessage response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
using (Stream contentStream = await response.Content.ReadAsStreamAsync())
using (FileStream fileStream = new FileStream(savePath, FileMode.Create))
{
var totalBytes = response.Content.Headers.ContentLength.GetValueOrDefault();
var buffer = new byte[8192];
long bytesRead = 0;
int bytesReceived;
while ((bytesReceived = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesReceived);
bytesRead += bytesReceived;
// 报告进度(如果有)
progress?.Report((float)bytesRead / totalBytes);
}
}
}
}
// 使用带进度条的示例
var progress = new Progress<float>(p => Console.WriteLine($"下载进度: {p:P}"));
await DownloadWithProgressAsync(
"https://example.com/largefile.zip",
@"C:\Downloads\largefile.zip",
progress
);
注意事项:
-
异常处理:务必添加 try-catch 处理网络异常、文件权限问题等
-
路径安全:检查本地路径是否合法,目录是否存在
csharp
var directory = Path.GetDirectoryName(savePath); if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
-
文件名提取:从URL自动获取文件名
csharp
string GetFileNameFromUrl(string url) { Uri uri = new Uri(url); return Path.GetFileName(uri.LocalPath); }
-
超时设置:
csharp
httpClient.Timeout = TimeSpan.FromMinutes(30); // 设置超时时间
-
取消支持:可添加 CancellationToken 支持取消操作
推荐方案:
-
现代应用使用 HttpClient + 异步流复制(方法1或方法3)
-
需要进度报告时使用带缓冲读取的方法3
-
简单脚本可使用 WebClient 简化代码
-
始终使用异步方法避免阻塞UI线程
根据实际需求选择合适的方法,并添加必要的错误处理和资源清理逻辑。