高效下载大文件

Download Large File Efficiently

提问人:Ashutosh Pandey 提问时间:11/17/2023 最后编辑:Svyatoslav DanylivAshutosh Pandey 更新时间:11/17/2023 访问量:98

问:

我编写了以下方法来下载文件并保存在 c# 中。.net framework 4.7.2

public static bool DownloadFiles(Uri url, string filePath)
{
    try
    {
        
        using (HttpClient client = new HttpClient())
        {
            using (var stream = client.GetStreamAsync(url))
            {
                using (var fs = new FileStream(filePath, FileMode.OpenOrCreate))
                {
                    stream.Result.CopyTo(fs);
                }
            }
        }
        return true;
    }
    catch (Exception ex)
    {
        
        return false;
    }
}

上面的代码对于大文件是有效的,我试图做一些性能分析,但没有得出一些明确的结论。我是 C# 的新手,因为它不是我的主要技术堆栈,任何建议都会非常有帮助。

C# HTTP

评论

0赞 nbk 11/17/2023
您应该考虑进行 asynchron 下载
0赞 Ashutosh Pandey 11/17/2023
你@nbk在说这个 - learn.microsoft.com/en-us/dotnet/api/......
0赞 nbk 11/17/2023
是的,还有更多的可能性,但没关系,而不是等待您需要在异步通信中投资 littele 的文件,然后您可以在后台下载
0赞 MakePeaceGreatAgain 11/17/2023
*我们应该如何知道 aboce 是否符合您的需求?你需要衡量自己,并检查你是否在使用该代码时遇到困难。

答:

3赞 Svyatoslav Danyliv 11/17/2023 #1

此函数应为异步函数。 不应释放 从 .NET 客户端调用 Web API (C#):HttpClient

public static class HttpUtils
{
    static HttpClient client = new HttpClient();

    public static async Task<bool> DownloadFilesAsync(Uri url, string filePath)
    {
        try
        {

            using (var stream = await client.GetStreamAsync(url))
            {
                using (var fs = new FileStream(filePath, FileMode.OpenOrCreate))
                {
                    await stream.CopyToAsync(fs);
                }
            }

            return true;
        }
        catch (Exception ex)
        {

            return false;
        }
    }
}

评论

0赞 Ashutosh Pandey 11/17/2023
感谢您的回复,此流是否以块形式获取,这会导致内存问题吗?client.GetStreamAsync(url)
0赞 Svyatoslav Danyliv 11/17/2023
是的,它是按块复制的。
0赞 Svyatoslav Danyliv 11/17/2023
CopyToAsync如果要配置缓冲区大小,也要重载。
1赞 Amit Mohanty 11/17/2023 #2

为了获得更好的性能,可以进行一些改进和考虑。

  • GetStreamAsync是一个异步方法,它返回 . 您应该使用它来获取实际流。Task<Stream>await
  • 对于大文件,使用 可能会消耗大量内存。 请考虑使用缓冲区从源流中读取数据块 并将它们写入目标流。CopyTo
public static async Task<bool> DownloadFiles(Uri url, string filePath)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            using (Stream stream = await client.GetStreamAsync(url))
            {
                using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
                {
                    byte[] buffer = new byte[8192]; // 8KB buffer (can adjust size)
                    int bytesRead;
                    while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        await fs.WriteAsync(buffer, 0, bytesRead);
                    }
                }
            }
        }
        return true;
    }
    catch (Exception ex)
    {
        // Handle exceptions appropriately (log, notify, etc.)
        Console.WriteLine(ex.Message);
        return false;
    }
}

评论

1赞 Magnus 11/17/2023
CopyTo 使用缓冲区,您甚至可以指定大小。