日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

使用 C# 下载文件的十八般武艺

發布時間:2023/12/4 C# 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用 C# 下载文件的十八般武艺 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文件下載是一個軟件開發中的常見需求。本文從最簡單的下載方式開始步步遞進,講述了文件下載過程中的常見問題并給出了解決方案。并展示了如何使用多線程提升 HTTP 的下載速度以及調用 aria2 實現非 HTTP 協議的文件下載。

簡單下載

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

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

異步下載

該方法也提供異步的實現:

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

下載文件的同時向服務器發送自定義請求頭

如果需要對文件下載請求進行定制,可以使用 HttpClient :

var url = "https://www.coderbusy.com"; var save = @"D:\1.html"; var http = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get,url); //增加 Auth 請求頭 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);} }

如何解決下載文件不完整的問題

以上所有代碼在應對小文件的下載時沒有特別大的問題,在網絡情況不佳或文件較大時容易引入錯誤。以下代碼在開發中很常見:

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

如果在 DownloadFileTaskAsync 方法中發生了異常(通常是網絡中斷或網絡超時),那么下載不完整的文件將會保留在本地系統中。在該任務重試執行時,因為文件已存在(雖然它不完整)所以會直接進入處理程序,從而引入異常。

一個簡單的修復方式時引入異常處理,但這種方式對應用程序意外終止造成的文件不完整無效:

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

筆者更喜歡的方式是引入一個臨時文件。下載操作將數據下載到臨時文件中,當確定下載操作執行完畢時將臨時文件改名:

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

使用 Downloader 進行 HTTP 多線程下載

在網絡帶寬充足的情況下,單線程下載的效率并不理想。我們需要多線程和斷點續傳才可以拿到更好的下載速度。

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

GitHub 開源地址:?https://github.com/bezzad/Downloader

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

從 NuGet 安裝 Downloader 之后,創建一個下載配置:

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

創建一個下載服務:

var downloader = new DownloadService(downloadOpt);

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

// Provide `FileName` and `TotalBytesToReceive` at the start of each downloads // 在每次下載開始時提供 "文件名 "和 "要接收的總字節數"。 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. // 提供有關分塊下載的信息,如每個分塊的進度百分比、速度、收到的總字節數和收到的字節數組,以實現實時流。 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. // 提供任何關于下載進度的信息,如進度百分比的塊數總和、總速度、平均速度、總接收字節數和接收字節數組的實時流。 downloader.DownloadProgressChanged += OnDownloadProgressChanged;// Download completed event that can include occurred errors or cancelled or download completed successfully. // 下載完成的事件,可以包括發生錯誤或被取消或下載成功。 downloader.DownloadFileCompleted += OnDownloadFileCompleted;

接著就可以下載文件了:

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

下載非 HTTP 協議的文件

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

aria2 是一個輕量級的多協議和多源命令行下載工具。它支持 HTTP/HTTPS、FTP、SFTP、BitTorrent 和 Metalink。aria2 可以通過內置的 JSON-RPC 和 XML-RPC 接口進行操作。

我們可以調用 aria2 實現文件下載功能。

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

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

將下載好的 aria2c.exe 復制到應用程序目錄,如果是其他系統則可以下載對應的二進制文件。

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("啟動 aria2c: {0}", args);using (var p = new Process { StartInfo = info, EnableRaisingEvents = true }){if (!p.Start()){throw new Exception("aria 啟動失敗");}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);} }

以上代碼通過命令行參數啟動了一個新的 aria2c 下載進程,并對下載進度信息輸出在了控制臺。調用方式如下:

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

總結

以上是生活随笔為你收集整理的使用 C# 下载文件的十八般武艺的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。