位置: 文档库 > C#(.NET) > C# 文件下载四方法

C# 文件下载四方法

梁启超 上传于 2023-07-16 01:46

《C# 文件下载四方法》

在.NET开发中,文件下载是常见的需求场景,无论是从本地路径读取文件还是从网络获取资源,都需要通过编程实现高效、安全的下载功能。本文将详细介绍四种C#中实现文件下载的核心方法,涵盖基础API调用、异步编程、第三方库集成以及高级场景处理,帮助开发者根据实际需求选择最优方案。

一、WebClient类:基础同步下载

WebClient是.NET Framework中最早的HTTP客户端类之一,适用于简单的同步文件下载场景。其核心方法为DownloadFile,可快速实现从URL到本地文件的保存。

using System.Net;

public void DownloadWithWebClient(string url, string savePath)
{
    using (WebClient client = new WebClient())
    {
        try
        {
            client.DownloadFile(url, savePath);
            Console.WriteLine("下载完成");
        }
        catch (WebException ex)
        {
            Console.WriteLine($"下载失败: {ex.Message}");
        }
    }
}

优点:代码简洁,适合小型文件或脚本场景。缺点:同步阻塞线程,无法取消或监控进度,.NET Core 3.1后已标记为过时。

二、HttpClient类:现代异步下载

HttpClient是.NET Core及后续版本推荐的HTTP客户端,支持异步操作、取消令牌和进度监控,是生产环境的主流选择。

1. 基础异步下载

using System.Net.Http;
using System.IO;

public async Task DownloadWithHttpClientAsync(string url, string savePath)
{
    using (HttpClient client = new HttpClient())
    {
        try
        {
            byte[] fileBytes = await client.GetByteArrayAsync(url);
            await File.WriteAllBytesAsync(savePath, fileBytes);
            Console.WriteLine("下载完成");
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"请求失败: {ex.Message}");
        }
    }
}

2. 流式下载(大文件优化)

对于大文件,应使用流式传输避免内存溢出:

public async Task DownloadLargeFileAsync(string url, string savePath)
{
    using (HttpClient client = new HttpClient())
    using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
    using (var contentStream = await response.Content.ReadAsStreamAsync())
    using (var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write))
    {
        await contentStream.CopyToAsync(fileStream);
        Console.WriteLine("大文件下载完成");
    }
}

3. 进度监控实现

通过自定义Progress实现下载进度显示:

public async Task DownloadWithProgressAsync(string url, string savePath)
{
    using (HttpClient client = new HttpClient())
    {
        var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
        var totalBytes = response.Content.Headers.ContentLength ?? 0;
        var buffer = new byte[8192];
        int bytesRead;
        long totalRead = 0;

        using (var contentStream = await response.Content.ReadAsStreamAsync())
        using (var fileStream = new FileStream(savePath, FileMode.Create))
        {
            while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await fileStream.WriteAsync(buffer, 0, bytesRead);
                totalRead += bytesRead;
                double progress = (double)totalRead / totalBytes * 100;
                Console.WriteLine($"进度: {progress:F2}%");
            }
        }
    }
}

三、FTP协议下载:专有协议实现

当需要从FTP服务器下载文件时,可使用FtpWebRequest类实现:

using System.Net;

public void DownloadFromFtp(string ftpUrl, string username, string password, string savePath)
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Credentials = new NetworkCredential(username, password);

    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    using (Stream responseStream = response.GetResponseStream())
    using (FileStream fileStream = File.Create(savePath))
    {
        responseStream.CopyTo(fileStream);
        Console.WriteLine($"FTP下载完成,状态: {response.StatusDescription}");
    }
}

注意事项:需处理SSL/TLS加密连接时,需设置EnableSsl属性为true。

四、第三方库FluentFTP:高级FTP操作

对于复杂的FTP需求,推荐使用FluentFTP库,提供更简洁的API和断点续传功能。

1. 安装与基础下载

// 通过NuGet安装FluentFTP
// Install-Package FluentFTP

using FluentFTP;

public async Task DownloadWithFluentFtpAsync(string host, string username, string password, 
    string remotePath, string localPath)
{
    using (var client = new FtpClient(host, username, password))
    {
        await client.ConnectAsync();
        await client.DownloadFileAsync(localPath, remotePath, FtpLocalExists.Overwrite, true);
        Console.WriteLine("FluentFTP下载完成");
    }
}

2. 断点续传实现

public async Task ResumeDownloadWithFluentFtpAsync(string host, string username, string password,
    string remotePath, string localPath)
{
    using (var client = new FtpClient(host, username, password))
    {
        await client.ConnectAsync();
        
        // 检查本地文件是否存在并获取已下载大小
        long existingSize = File.Exists(localPath) ? new FileInfo(localPath).Length : 0;
        
        await client.DownloadFileAsync(localPath, remotePath, 
            existingSize > 0 ? FtpLocalExists.Resume : FtpLocalExists.Overwrite, 
            true, 
            existingSize);
        
        Console.WriteLine("断点续传完成");
    }
}

五、高级场景处理

1. 多线程分段下载

通过Range头实现多线程并行下载:

public async Task MultiThreadDownloadAsync(string url, string savePath, int threadCount = 4)
{
    using (HttpClient client = new HttpClient())
    {
        var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));
        long totalSize = long.Parse(response.Content.Headers.ContentLength.ToString());
        long partSize = totalSize / threadCount;

        var tasks = new List();
        for (int i = 0; i 

2. 下载限速控制

通过自定义HttpMessageHandler实现限速:

public class RateLimitedHandler : DelegatingHandler
{
    private readonly int _bytesPerSecond;
    private long _totalBytes;
    private DateTime _lastCheckTime;

    public RateLimitedHandler(int bytesPerSecond)
    {
        _bytesPerSecond = bytesPerSecond;
        _lastCheckTime = DateTime.Now;
    }

    protected override async Task SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        var contentStream = await response.Content.ReadAsStreamAsync();
        
        var memoryStream = new MemoryStream();
        var buffer = new byte[8192];
        int bytesRead;

        while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            await memoryStream.WriteAsync(buffer, 0, bytesRead);
            _totalBytes += bytesRead;
            
            var timeElapsed = (DateTime.Now - _lastCheckTime).TotalSeconds;
            if (timeElapsed > 0 && _totalBytes / timeElapsed > _bytesPerSecond)
            {
                await Task.Delay(100); // 简单限速实现
            }
        }

        response.Content = new StreamContent(memoryStream);
        return response;
    }
}

// 使用示例
public async Task LimitedDownloadAsync(string url, string savePath)
{
    var handler = new RateLimitedHandler(1024 * 100); // 限制100KB/s
    var client = new HttpClient(handler);
    
    var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
    // 后续处理...
}

六、最佳实践总结

1. 资源管理:始终使用using语句确保流和客户端正确释放

2. 异常处理:区分网络异常、IO异常和业务异常

3. 异步编程:优先使用async/await避免线程阻塞

4. 大文件处理:采用流式传输而非全量缓冲

5. 安全性:验证URL合法性,防止路径遍历攻击

6. 进度反馈:通过IProgress或事件机制提供下载进度

关键词:C#文件下载、HttpClient、WebClient、FTP下载、FluentFTP、异步编程多线程下载、断点续传、限速控制

简介:本文详细介绍了C#中四种文件下载方法,包括基础WebClient类、现代HttpClient异步实现、FTP协议下载及FluentFTP第三方库应用,覆盖了同步/异步、大文件处理、进度监控、断点续传等高级场景,提供了完整的代码示例和最佳实践建议。