1、直接下載
using (HttpClient http = new HttpClient()) { var httpResponseMessage = await http.GetAsync("http://localhost:813/新建文件夾2.rar", HttpCompletionOption.ResponseHeadersRead);//發送請求 var contentLength = httpResponseMessage.Content.Headers.ContentLength;//讀取文件大小
using (var stream = await httpResponseMessage.Content.ReadAsStreamAsync())//讀取文件流 { var readLength = 1024000;//1000K 每次讀取大小 byte[] bytes = new byte[readLength]; int writeLength; while ((writeLength = stream.Read(bytes, 0, readLength)) > 0)//分塊讀取文件流 { using (FileStream fs = new FileStream(Application.StartupPath + "/temp.rar", FileMode.Append, FileAccess.Write))//使用追加方式打開一個文件流 { fs.Write(bytes, 0, writeLength);//追加寫入文件 contentLength -= writeLength; if (contentLength == 0)//如果寫入完成 給出提示 MessageBox.Show("下載完成"); } } } }
2、異步下載
//開啟一個異步線程 await Task.Run(async () => { //異步操作UI元素 label1.Invoke((Action)(() => { label1.Text = "准備下載..."; })); long downloadSize = 0;//已經下載大小 long downloadSpeed = 0;//下載速度 using (HttpClient http = new HttpClient()) { var httpResponseMessage = await http.GetAsync("http://localhost:8088/wms_manual.pdf", HttpCompletionOption.ResponseHeadersRead);//發送請求 var contentLength = httpResponseMessage.Content.Headers.ContentLength; //文件大小 // using (var stream = await httpResponseMessage.Content.ReadAsStreamAsync()) { var readLength = 1024000;//1000K byte[] bytes = new byte[readLength]; int writeLength; var beginSecond = DateTime.Now.Second;//當前時間秒 while ((writeLength = stream.Read(bytes, 0, readLength)) > 0) { //使用追加方式打開一個文件流 using (FileStream fs = new FileStream(Application.StartupPath + "/temp.rar", FileMode.Append, FileAccess.Write)) { fs.Write(bytes, 0, writeLength); } downloadSize += writeLength; downloadSpeed += writeLength; progressBar1.Invoke((Action)(() => { var endSecond = DateTime.Now.Second; if (beginSecond != endSecond)//計算速度 { downloadSpeed = downloadSpeed / (endSecond - beginSecond); label1.Text = "下載速度" + downloadSpeed / 1024 + "KB/S"; beginSecond = DateTime.Now.Second; downloadSpeed = 0;//清空 } progressBar1.Value = Math.Max((int)(downloadSize * 100 / contentLength), 1); })); } label1.Invoke((Action)(() => { label1.Text = "下載完成"; })); } } });
3、斷點續傳
/// <summary> /// 是否暫停 /// </summary> static bool isPause = true; /// <summary> /// 下載開始位置(也就是已經下載了的位置) /// </summary> static long rangeBegin = 0;//(當然,這個值也可以存為持久化。如文本、數據庫等) /// <summary> /// 斷線續傳 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void button3_ClickAsync(object sender, EventArgs e) { isPause = !isPause; if (!isPause)//點擊下載 { button3.Text = "暫停"; await Task.Run(async () => { //異步操作UI元素 label1.Invoke((Action)(() => { label1.Text = "准備下載..."; })); long downloadSpeed = 0;//下載速度 using (HttpClient http = new HttpClient()) { //var url = "http://localhost:813/新建文件夾2.rar"; //a標簽下載鏈接 var url = "http://localhost:8088/wms_manual.pdf"; //我們自己實現的服務端下載鏈接 var request = new HttpRequestMessage { RequestUri = new Uri(url) }; request.Headers.Range = new RangeHeaderValue(rangeBegin, null);//【關鍵點】全局變量記錄已經下載了多少,然后下次從這個位置開始下載。 var httpResponseMessage = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); var contentLength = httpResponseMessage.Content.Headers.ContentLength;//本次請求的內容大小 if (httpResponseMessage.Content.Headers.ContentRange != null) //如果為空,則說明服務器不支持斷點續傳 { contentLength = httpResponseMessage.Content.Headers.ContentRange.Length;//服務器上的文件大小 } using (var stream = await httpResponseMessage.Content.ReadAsStreamAsync()) { var readLength = 1024000;//1000K byte[] bytes = new byte[readLength]; int writeLength; var beginSecond = DateTime.Now.Second;//當前時間秒 while ((writeLength = stream.Read(bytes, 0, readLength)) > 0 && !isPause) { //使用追加方式打開一個文件流 using (FileStream fs = new FileStream(Application.StartupPath + "/temp.rar", FileMode.Append, FileAccess.Write)) { fs.Write(bytes, 0, writeLength); } downloadSpeed += writeLength; rangeBegin += writeLength; progressBar1.Invoke((Action)(() => { var endSecond = DateTime.Now.Second; if (beginSecond != endSecond)//計算速度 { downloadSpeed = downloadSpeed / (endSecond - beginSecond); label1.Text = "下載速度" + downloadSpeed / 1024 + "KB/S"; beginSecond = DateTime.Now.Second; downloadSpeed = 0;//清空 } progressBar1.Value = Math.Max((int)((rangeBegin) * 100 / contentLength), 1); })); } if (rangeBegin == contentLength) { label1.Invoke((Action)(() => { label1.Text = "下載完成"; })); } } } }); } else//點擊暫停 { button3.Text = "繼續下載"; label1.Text = "暫停下載"; } }
4、多線程下載文件
/// <summary> /// 多線程下載文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void button4_ClickAsync(object sender, EventArgs e) { using (HttpClient http = new HttpClient()) { var url = "http://localhost:8088/wms_manual.pdf"; var httpResponseMessage = await http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); var contentLength = httpResponseMessage.Content.Headers.ContentLength.Value; var size = contentLength / 10; //這里為了方便,就直接分成10個線程下載。(當然這是不合理的) var tasks = new List<Task>(); for (int i = 0; i < 10; i++) { var begin = i * size; var end = begin + size - 1; var task = FileDownload(url, begin, end, i); tasks.Add(task); } for (int i = 0; i < 10; i++) { await tasks[i]; //當然,這里如有下載異常沒有考慮、文件也沒有校驗。各位自己完善吧。 progressBar1.Value = (i + 1) * 10; } FileMerge(Application.StartupPath + @"\File", "temp.rar"); label1.Text = "下載完成"; } } /// <summary> /// 文件下載 /// (如果你有興趣,可以沒個線程弄個進度條) /// </summary> /// <param name="begin"></param> /// <param name="end"></param> /// <param name="index"></param> /// <returns></returns> public Task FileDownload(string url, long begin, long end, int index) { var task = Task.Run(async () => { using (HttpClient http = new HttpClient()) { var request = new HttpRequestMessage { RequestUri = new Uri(url) }; request.Headers.Range = new RangeHeaderValue(begin, end);//【關鍵點】全局變量記錄已經下載了多少,然后下次從這個位置開始下載。 var httpResponseMessage = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); using (var stream = await httpResponseMessage.Content.ReadAsStreamAsync()) { var readLength = 1024000;//1000K byte[] bytes = new byte[readLength]; int writeLength; var beginSecond = DateTime.Now.Second;//當前時間秒 var filePaht = Application.StartupPath + "/File/"; if (!Directory.Exists(filePaht)) Directory.CreateDirectory(filePaht); try { while ((writeLength = stream.Read(bytes, 0, readLength)) > 0) { //使用追加方式打開一個文件流 using (FileStream fs = new FileStream(filePaht + index, FileMode.Append, FileAccess.Write)) { fs.Write(bytes, 0, writeLength); } } } catch (Exception) { //如果出現異常則刪掉這個文件 File.Delete(filePaht + index); } } } }); return task; } /// <summary> /// 合並文件 /// </summary> /// <param name="path"></param> /// <returns></returns> public bool FileMerge(string path, string fileName) { //這里排序一定要正確,轉成數字后排序(字符串會按1 10 11排序,默認10比2小) foreach (var filePath in Directory.GetFiles(path).OrderBy(t => int.Parse(Path.GetFileNameWithoutExtension(t)))) { using (FileStream fs = new FileStream(Directory.GetParent(path).FullName + @"\" + fileName, FileMode.Append, FileAccess.Write)) { byte[] bytes = System.IO.File.ReadAllBytes(filePath);//讀取文件到字節數組 fs.Write(bytes, 0, bytes.Length);//寫入文件 } System.IO.File.Delete(filePath); } Directory.Delete(path); return true; }