基于C#的高效大文件下载器

以下方法的优势:

  1. 高效性:采用HttpClient进行异步请求,减少了线程阻塞,提高下载速度,使用缓冲区分块读取和写入文件,避免一次性加载整个文件,节省内存。
  2. 提升用户体验:实时输出下载进度,用户可以清楚地了解下载的状态,提升用户体验。
  3. 支持大文件下载:将下载功能封装在静态方法中,便于在不同项目或场景中重复使用。
using System; // 引入基础功能的命名空间
using System.Net.Http; // 引入处理HTTP请求的命名空间
using System.Threading.Tasks; // 引入处理异步任务的命名空间
using System.IO; // 引入处理文件输入输出的命名空间

public class FileDownloader
{
    // 静态HttpClient实例,用于发起HTTP请求,避免多次创建带来的开销
    private static readonly HttpClient httpClient = new HttpClient();

    // 异步方法,用于下载文件,接受URL和目标路径作为参数
    public static async Task DownloadFileAsync(string url, string destinationPath)
    {
        // 检查URL是否为空或只包含空白字符,如果是则抛出异常
        if (string.IsNullOrWhiteSpace(url))
            throw new ArgumentException("URL 不能为 null 或空", nameof(url));

        // 检查目标路径是否为空或只包含空白字符,如果是则抛出异常
        if (string.IsNullOrWhiteSpace(destinationPath))
            throw new ArgumentException("目标路径不能为 null 或为空", nameof(destinationPath));

        try
        {
            // 发送GET请求以获取指定URL的响应,设置为只读取响应头
            using (HttpResponseMessage response = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
            {
                // 确保响应是成功的状态码
                response.EnsureSuccessStatusCode();

                // 获取文件的总大小,以便进行切片下载
                long totalBytes = response.Content.Headers.ContentLength ?? -1;
                const int bufferSize = 8192; // 定义缓冲区大小为8KB
                byte[] buffer = new byte[bufferSize]; // 创建缓冲区以存储下载的数据

                // 使用FileStream异步创建文件流并写入文件
                using (Stream contentStream = await response.Content.ReadAsStreamAsync(),
                              fileStream = new FileStream(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize, useAsync: true))
                {
                    long totalReadBytes = 0; // 记录已读取的字节数
                    int bytesRead; // 当前读取的字节数

                    // 循环读取数据直到内容流结束
                    while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        // 将缓冲区中的数据写入文件流
                        await fileStream.WriteAsync(buffer, 0, bytesRead);
                        totalReadBytes += bytesRead; // 更新已读取的字节数

                        // 输出下载进度
                        if (totalBytes > 0)
                        {
                            Console.WriteLine($"下载{totalReadBytes} of {totalBytes} 字节.");
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            // 捕获并输出异常信息,然后重新抛出异常
            Console.WriteLine($"错误: {ex.Message}");
            throw;
        }
    }
}

你可能感兴趣的:(C#,.NET,Framework,c#,开发语言,后端,经验分享)