最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用 C# 下載文件的多種方法小結(jié)

 更新時(shí)間:2021年08月21日 09:50:51   作者:Soar、毅  
本文從最簡(jiǎn)單的下載方式開(kāi)始步步遞進(jìn),講述了文件下載過(guò)程中的常見(jiàn)問(wèn)題并給出了解決方案。并展示了如何使用多線(xiàn)程提升 HTTP 的下載速度以及調(diào)用 aria2 實(shí)現(xiàn)非 HTTP 協(xié)議的文件下載,對(duì)C# 下載文件相關(guān)知識(shí)感興趣的朋友一起看看吧

文件下載是一個(gè)軟件開(kāi)發(fā)中的常見(jiàn)需求。本文從最簡(jiǎn)單的下載方式開(kāi)始步步遞進(jìn),講述了文件下載過(guò)程中的常見(jiàn)問(wèn)題并給出了解決方案。并展示了如何使用多線(xiàn)程提升 HTTP 的下載速度以及調(diào)用 aria2 實(shí)現(xiàn)非 HTTP 協(xié)議的文件下載。

簡(jiǎn)單下載

在 .NET 程序中下載文件最簡(jiǎn)單的方式就是使用 WebClient 的 DownloadFile 方法:

 var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    using (var web = new WebClient())
    {
        web.DownloadFile(url,save);
    }

異步下載

該方法也提供異步的實(shí)現(xiàn):

 var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    using (var web = new WebClient())
    {
        await web.DownloadFileTaskAsync(url, save);
    }

下載文件的同時(shí)向服務(wù)器發(fā)送自定義請(qǐng)求頭

如果需要對(duì)文件下載請(qǐng)求進(jìn)行定制,可以使用 HttpClient :

var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    var http = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get,url);
    //增加 Auth 請(qǐng)求頭
    request.Headers.Add("Auth","123456");
    var response = await http.SendAsync(request);
    response.EnsureSuccessStatusCode();
    using (var fs = File.Open(save, FileMode.Create))
    {
        using (var ms = response.Content.ReadAsStream())
        {
            await ms.CopyToAsync(fs);
        }
    }

如何解決下載文件不完整的問(wèn)題

以上所有代碼在應(yīng)對(duì)小文件的下載時(shí)沒(méi)有特別大的問(wèn)題,在網(wǎng)絡(luò)情況不佳或文件較大時(shí)容易引入錯(cuò)誤。以下代碼在開(kāi)發(fā)中很常見(jiàn):

  var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    if (!File.Exists(save))
    {
        Console.WriteLine("文件不存在,開(kāi)始下載...");
        using (var web = new WebClient())
        {
            await web.DownloadFileTaskAsync(url, save);
        }
        Console.WriteLine("文件下載成功");
    }
    Console.WriteLine("開(kāi)始處理文件");
    //TODO:對(duì)文件進(jìn)行處理

如果在 DownloadFileTaskAsync 方法中發(fā)生了異常(通常是網(wǎng)絡(luò)中斷或網(wǎng)絡(luò)超時(shí)),那么下載不完整的文件將會(huì)保留在本地系統(tǒng)中。在該任務(wù)重試執(zhí)行時(shí),因?yàn)槲募汛嬖冢m然它不完整)所以會(huì)直接進(jìn)入處理程序,從而引入異常。

一個(gè)簡(jiǎn)單的修復(fù)方式是引入異常處理,但這種方式對(duì)應(yīng)用程序意外終止造成的文件不完整無(wú)效:

 var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    if (!File.Exists(save))
    {
        Console.WriteLine("文件不存在,開(kāi)始下載...");
        using (var web = new WebClient())
        {
            try
            {
                await web.DownloadFileTaskAsync(url, save);
            }
            catch
            {
                if (File.Exists(save))
                {
                    File.Delete(save);
                }
                throw;
            }
        }
        Console.WriteLine("文件下載成功");
    }
    Console.WriteLine("開(kāi)始處理文件");
    //TODO:對(duì)文件進(jìn)行處理

筆者更喜歡的方式是引入一個(gè)臨時(shí)文件。下載操作將數(shù)據(jù)下載到臨時(shí)文件中,當(dāng)確定下載操作執(zhí)行完畢時(shí)將臨時(shí)文件改名:

var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    if (!File.Exists(save))
    {
        Console.WriteLine("文件不存在,開(kāi)始下載...");
        //先下載到臨時(shí)文件
        var tmp = save + ".tmp";
        using (var web = new WebClient())
        {
            await web.DownloadFileTaskAsync(url, tmp);
        }
        File.Move(tmp, save, true);
        Console.WriteLine("文件下載成功");
    }
    Console.WriteLine("開(kāi)始處理文件");
    //TODO:對(duì)文件進(jìn)行處理

使用 Downloader 進(jìn)行 HTTP 多線(xiàn)程下載

在網(wǎng)絡(luò)帶寬充足的情況下,單線(xiàn)程下載的效率并不理想。我們需要多線(xiàn)程和斷點(diǎn)續(xù)傳才可以拿到更好的下載速度。

Downloader 是一個(gè)現(xiàn)代化的、流暢的、異步的、可測(cè)試的和可移植的 .NET 庫(kù)。這是一個(gè)包含異步進(jìn)度事件的多線(xiàn)程下載程序。Downloader 與 .NET Standard 2.0 及以上版本兼容,可以在 Windows、Linux 和 macOS 上運(yùn)行。

GitHub 開(kāi)源地址: https://github.com/bezzad/Downloader

NuGet 地址:https://www.nuget.org/packages/Downloader

從 NuGet 安裝 Downloader 之后,創(chuàng)建一個(gè)下載配置:

 var downloadOpt = new DownloadConfiguration()
    {
        BufferBlockSize = 10240, // 通常,主機(jī)最大支持8000字節(jié),默認(rèn)值為8000。
        ChunkCount = 8, // 要下載的文件分片數(shù)量,默認(rèn)值為1
        MaximumBytesPerSecond = 1024 * 1024, // 下載速度限制為1MB/s,默認(rèn)值為零或無(wú)限制
        MaxTryAgainOnFailover = int.MaxValue, // 失敗的最大次數(shù)
        OnTheFlyDownload = false, // 是否在內(nèi)存中進(jìn)行緩存? 默認(rèn)值是true
        ParallelDownload = true, // 下載文件是否為并行的。默認(rèn)值為false
        TempDirectory = "C:\\temp", // 設(shè)置用于緩沖大塊文件的臨時(shí)路徑,默認(rèn)路徑為Path.GetTempPath()。
        Timeout = 1000, // 每個(gè) stream reader  的超時(shí)(毫秒),默認(rèn)值是1000
        RequestConfiguration = // 定制請(qǐng)求頭文件
        {
            Accept = "*/*",
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
            CookieContainer =  new CookieContainer(), // Add your cookies
            Headers = new WebHeaderCollection(), // Add your custom headers
            KeepAlive = false,
            ProtocolVersion = HttpVersion.Version11, // Default value is HTTP 1.1
            UseDefaultCredentials = false,
            UserAgent = $"DownloaderSample/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}"
        }
    };

創(chuàng)建一個(gè)下載服務(wù):

var downloader = new DownloadService(downloadOpt);

配置事件處理器(該步驟可以省略):

// Provide `FileName` and `TotalBytesToReceive` at the start of each downloads
    // 在每次下載開(kāi)始時(shí)提供 "文件名 "和 "要接收的總字節(jié)數(shù)"。
    downloader.DownloadStarted += OnDownloadStarted;

    // Provide any information about chunker downloads, like progress percentage per chunk, speed, total received bytes and received bytes array to live streaming.
    // 提供有關(guān)分塊下載的信息,如每個(gè)分塊的進(jìn)度百分比、速度、收到的總字節(jié)數(shù)和收到的字節(jié)數(shù)組,以實(shí)現(xiàn)實(shí)時(shí)流。
    downloader.ChunkDownloadProgressChanged += OnChunkDownloadProgressChanged;

    // Provide any information about download progress, like progress percentage of sum of chunks, total speed, average speed, total received bytes and received bytes array to live streaming.
    // 提供任何關(guān)于下載進(jìn)度的信息,如進(jìn)度百分比的塊數(shù)總和、總速度、平均速度、總接收字節(jié)數(shù)和接收字節(jié)數(shù)組的實(shí)時(shí)流。
    downloader.DownloadProgressChanged += OnDownloadProgressChanged;

    // Download completed event that can include occurred errors or cancelled or download completed successfully.
    // 下載完成的事件,可以包括發(fā)生錯(cuò)誤或被取消或下載成功。
    downloader.DownloadFileCompleted += OnDownloadFileCompleted;

接著就可以下載文件了:

string file = @"D:\1.html";
    string url = @"https://www.coderbusy.com";
    await downloader.DownloadFileTaskAsync(url, file);

下載非 HTTP 協(xié)議的文件

除了 WebClient 可以下載 FTP 協(xié)議的文件之外,上文所示的其他方法只能下載 HTTP 協(xié)議的文件。

aria2 是一個(gè)輕量級(jí)的多協(xié)議和多源命令行下載工具。它支持 HTTP/HTTPS、FTP、SFTP、BitTorrent 和 Metalink。aria2 可以通過(guò)內(nèi)置的 JSON-RPC 和 XML-RPC 接口進(jìn)行操作。

我們可以調(diào)用 aria2 實(shí)現(xiàn)文件下載功能。

GitHub 地址:https://github.com/aria2/aria2

下載地址:https://github.com/aria2/aria2/releases

將下載好的 aria2c.exe 復(fù)制到應(yīng)用程序目錄,如果是其他系統(tǒng)則可以下載對(duì)應(yīng)的二進(jìn)制文件。

 public static async Task Download(string url, string fn)
    {
        var exe = "aria2c";
        var dir = Path.GetDirectoryName(fn);
        var name = Path.GetFileName(fn);

        void Output(object sender, DataReceivedEventArgs args)
        {
            if (string.IsNullOrWhiteSpace(args.Data))
            {
                return;
            }
            Console.WriteLine("Aria:{0}", args.Data?.Trim());
        }

        var args = $"-x 8 -s 8 --dir={dir} --out={name} {url}";
        var info = new ProcessStartInfo(exe, args)
        {
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
        };
        if (File.Exists(fn))
        {
            File.Delete(fn);
        }

        Console.WriteLine("啟動(dòng) aria2c: {0}", args);
        using (var p = new Process { StartInfo = info, EnableRaisingEvents = true })
        {
            if (!p.Start())
            {
                throw new Exception("aria 啟動(dòng)失敗");
            }
            p.ErrorDataReceived += Output;
            p.OutputDataReceived += Output;
            p.BeginOutputReadLine();
            p.BeginErrorReadLine();
            await p.WaitForExitAsync();
            p.OutputDataReceived -= Output;
            p.ErrorDataReceived -= Output;
        }

        var fi = new FileInfo(fn);
        if (!fi.Exists || fi.Length == 0)
        {
            throw new FileNotFoundException("文件下載失敗", fn);
        }
    }

以上代碼通過(guò)命令行參數(shù)啟動(dòng)了一個(gè)新的 aria2c 下載進(jìn)程,并對(duì)下載進(jìn)度信息輸出在了控制臺(tái)。調(diào)用方式如下:

 var url = "https://www.coderbusy.com";
    var save = @"D:\1.html";
    await Download(url, save);

到此這篇關(guān)于使用 C# 下載文件的十八般武藝的文章就介紹到這了,更多相關(guān)C# 下載文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#代碼操作XML進(jìn)行增、刪、改操作

    C#代碼操作XML進(jìn)行增、刪、改操作

    這篇文章主要為大家詳細(xì)介紹了C# 代碼操作XML進(jìn)行增、刪、改操作,感興趣的小伙伴們可以參考一下
    2016-07-07
  • c#基礎(chǔ)系列之System.String的深入理解

    c#基礎(chǔ)系列之System.String的深入理解

    這篇文章主要給大家介紹了關(guān)于c#基礎(chǔ)系列之System.String的深入理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • 在.NET?WebService中跨域CORS問(wèn)題的解決方案

    在.NET?WebService中跨域CORS問(wèn)題的解決方案

    在現(xiàn)代的Web應(yīng)用程序開(kāi)發(fā)中,跨域資源共享(Cross-Origin?Resource?Sharing,?CORS)問(wèn)題是開(kāi)發(fā)者經(jīng)常遇到的一個(gè)挑戰(zhàn),在這篇博客中,我們將深入探討如何在?.NET?WebService?中解決CORS問(wèn)題,幫助開(kāi)發(fā)者順利實(shí)現(xiàn)跨域請(qǐng)求,需要的朋友可以參考下
    2024-05-05
  • C#實(shí)現(xiàn)json格式數(shù)據(jù)解析功能的方法詳解

    C#實(shí)現(xiàn)json格式數(shù)據(jù)解析功能的方法詳解

    這篇文章主要介紹了C#實(shí)現(xiàn)json格式數(shù)據(jù)解析功能的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了C#解析json格式數(shù)據(jù)的具體操作步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-12-12
  • C#使用WMI獲取硬盤(pán)參數(shù)的實(shí)現(xiàn)方法

    C#使用WMI獲取硬盤(pán)參數(shù)的實(shí)現(xiàn)方法

    因?yàn)樾枨笮枰婕矮@取硬盤(pán)的SN參數(shù),但是又不想要獲取到U盤(pán)或移動(dòng)硬盤(pán)設(shè)備的SN,所以就淺淺的研究了一下,本文給大家介紹了C#使用WMI獲取硬盤(pán)參數(shù)的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2024-06-06
  • C#使用命名管道Pipe進(jìn)行進(jìn)程通信實(shí)例詳解

    C#使用命名管道Pipe進(jìn)行進(jìn)程通信實(shí)例詳解

    這篇文章主要介紹了C#使用命名管道Pipe進(jìn)行進(jìn)程通信實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • C#泛型的逆變協(xié)變之個(gè)人理解

    C#泛型的逆變協(xié)變之個(gè)人理解

    這篇文章主要介紹了C#泛型的逆變協(xié)變之個(gè)人理解,需要的朋友可以參考下
    2023-04-04
  • C# WebApi Get請(qǐng)求方式傳遞實(shí)體參數(shù)的方法示例

    C# WebApi Get請(qǐng)求方式傳遞實(shí)體參數(shù)的方法示例

    這篇文章主要給大家介紹了關(guān)于C# WebApi Get請(qǐng)求方式傳遞實(shí)體參數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • C#常見(jiàn)的幾種集合 ArrayList,Hashtable,List<T>,Dictionary<K,V> 遍歷方法對(duì)比

    C#常見(jiàn)的幾種集合 ArrayList,Hashtable,List<T>,Dictionary<K,

    本文對(duì)C#中常見(jiàn)集合ArrayList,Hashtable,List<T>,Dictionary<K,V>遍歷方法做了簡(jiǎn)單的對(duì)比和介紹,有需要的朋友可以參考一下。
    2016-03-03
  • C# winfroms使用socket客戶(hù)端服務(wù)端的示例代碼

    C# winfroms使用socket客戶(hù)端服務(wù)端的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C# winfroms使用socket客戶(hù)端服務(wù)端的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02

最新評(píng)論

嘉兴市| 娄烦县| 图木舒克市| 甘肃省| 徐水县| 新民市| 泊头市| 杂多县| 防城港市| 来凤县| 古交市| 保亭| 石城县| 正镶白旗| 平罗县| 炎陵县| 图片| 嘉峪关市| 南京市| 松溪县| 平邑县| 疏附县| 庆安县| 乐都县| 黑水县| 平顺县| 景洪市| 仲巴县| 平谷区| 永年县| 肥城市| 广南县| 毕节市| 大余县| 阿拉尔市| 从化市| 南昌市| 景谷| 台州市| 榆林市| 延津县|