- [DEVEXPRESS] Chia sẻ code các tạo report in nhiều hóa đơn trên XtraReport C#
- [POWER AUTOMATE] Hướng dẫn gởi tin nhắn zalo từ file Excel - No code
- [C#] Chia sẻ code lock và unlock user trong domain Window
- [SOFTWARE] Giới thiệu bộ phần mềm tính Kết Cấu Thép HatteSale, Mộng Đơn, Dầm, Sàn, Móng Cọc, Vách, Xà Gồ, Tính Tải Trọng
- [DEVEXPRESS] Vẽ Biểu Đồ Stock Chứng Khoán - Công Cụ Thiết Yếu Cho Nhà Đầu Tư trên Winform
- [C#] Hướng dẫn bảo mật ứng dụng 2FA (Multi-factor Authentication) trên Winform
- [C#] Hướng dẫn convert HTML code sang PDF File trên NetCore 7 Winform
- [C#] Hướng dẫn viết ứng dụng chat với Gemini AI Google Winform
- Hướng dẫn khóa file bằng nhiều process id, không cho xóa tập tin
- Hướng dẫn cách tạo Product Id cho ứng dụng phần mềm XXXXX-XXXXX-XXXXX-XXXXX
- [SQLSERVER] Hướng dẫn tạo script sql từ ứng dụng Sqlserver management Studio
- [C#] Hướng dẫn sử dụng thư viện AutoITx lấy id và password Ultraviewer trên winform
- [VB.NET] Hướng dẫn lấy thông tin tài khoản đăng nhập windows và khởi động lại ứng dụng ở chế độ Administrator
- [C#] Sử dụng thư viện Polly gửi lại request api khi request bị lỗi hay rớt mạng
- [DEVEXPRESS] Chia sẻ source code tạo báo cáo report in tem nhãn label trên C# winform
- [DEVEXPRESS] Hướng dẫn vẽ biểu đồ Bar Chart trên Winform
- [C#] Tạo form đăng nhập và đăng ký với hiệu ứng Sliding Animation Effect
- [C#] Hướng dẫn tạo thanh toán đơn hàng qua mã vạch VietQR sử dụng API PayOS hoàn toàn miễn phí
- [C#] Hướng dẫn ghi log ra RichTextBox giống Console trên Winform sử dụng thư viện Serilog
- [C#] Hướng dẫn cách tạo mã QR Code trên file Excel
[C#] Chia sẽ Class Download file chia thành nhiều phần nhỏ để tải
Xin chào các bạn, bài viết này mình sẽ tiếp tục chia sẽ đến các bạn Class Downloader.cs, dùng để download file lớn thành từng File nhỏ trong lập trình C# Winform.
[C#] Download Segment part File
Trong các chương trình download, như ứng dụng download file nổi tiếng: Internet Download Manager.
Khi các bạn download một tập tin File lớn khoảng vài GB, thì với thiết bị máy tính hiện nay sử dụng nhiều CORE.
Thì cách chia nhỏ file ra sử dụng Parallels download để sử dụng rất phổ biến.
Ví dụ: bạn download 1 File Windows 4GB.
Các bạn có thể tùy chỉnh tách nhỏ file thành số phần do bạn quy định. Thường mình sẽ chọn chia thành 8 phần.
Sau khi download 8 file này sau, sẽ thực hiện bước cuối cùng là nối các file temp này lại với nhau.
Sau khi nối file download hoàn tất, thì chúng ta sẽ xóa đi những file temp này.
Trong class này File download temp sẽ được lưu trong thư mục đặc biệt special folder C:
Các bạn có thể gõ %temp%, để xem khi download.
Hình ảnh demo mình download ứng dụng Teamviewer:
Source code C# Class Download.cs
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace SplitDownload
{
public static class Downloader
{
static object MYlOCK = new object();
static Downloader()
{
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = 100;
ServicePointManager.MaxServicePointIdleTime = 1000;
}
public static DownloadResult Download(String fileUrl, String destinationFolderPath, int numberOfParallelDownloads = 0, bool validateSSL = false)
{
if (!validateSSL)
{
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
}
Uri uri = new Uri(fileUrl);
//Calculate destination path
String destinationFilePath = Path.Combine(destinationFolderPath, uri.Segments.Last());
DownloadResult result = new DownloadResult() { FilePath = destinationFilePath };
//Handle number of parallel downloads
if (numberOfParallelDownloads <= 0)
{
numberOfParallelDownloads = Environment.ProcessorCount;
}
#region Get file size
WebRequest webRequest = HttpWebRequest.Create(fileUrl);
webRequest.Method = "HEAD";
long responseLength;
using (WebResponse webResponse = webRequest.GetResponse())
{
responseLength = long.Parse(webResponse.Headers.Get("Content-Length"));
result.Size = responseLength;
}
#endregion
if (File.Exists(destinationFilePath))
{
File.Delete(destinationFilePath);
}
using (FileStream destinationStream = new FileStream(destinationFilePath, FileMode.Append))
{
ConcurrentDictionary<long, String> tempFilesDictionary = new ConcurrentDictionary<long, String>();
#region Calculate ranges
List<Range> readRanges = new List<Range>();
for (int chunk = 0; chunk < numberOfParallelDownloads - 1; chunk++)
{
var range = new Range()
{
Start = chunk * (responseLength / numberOfParallelDownloads),
End = ((chunk + 1) * (responseLength / numberOfParallelDownloads)) - 1
};
readRanges.Add(range);
}
readRanges.Add(new Range()
{
Start = readRanges.Any() ? readRanges.Last().End + 1 : 0,
End = responseLength - 1
});
#endregion
DateTime startTime = DateTime.Now;
#region Parallel download
int index = 0;
Parallel.ForEach(readRanges, new ParallelOptions() { MaxDegreeOfParallelism = numberOfParallelDownloads }, readRange =>
{
HttpWebRequest httpWebRequest = HttpWebRequest.Create(fileUrl) as HttpWebRequest;
httpWebRequest.Method = "GET";
httpWebRequest.AddRange(readRange.Start, readRange.End);
using (HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse)
{
String tempFilePath = Path.GetTempFileName();
using (var fileStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.Write))
{
httpWebResponse.GetResponseStream().CopyTo(fileStream);
lock (Downloader.MYlOCK)
{
result.PROGRESS += fileStream.Length;
var percent = 1.0 * result.PROGRESS / result.Size;
Debug.WriteLine("Progress: " + percent);
}
tempFilesDictionary.TryAdd(readRange.Start, tempFilePath);
}
}
index++;
});
result.ParallelDownloads = index;
#endregion
result.TimeTaken = DateTime.Now.Subtract(startTime);
#region Merge to single file
foreach (var tempFile in tempFilesDictionary.OrderBy(b => b.Key))
{
byte[] tempFileBytes = File.ReadAllBytes(tempFile.Value);
destinationStream.Write(tempFileBytes, 0, tempFileBytes.Length);
File.Delete(tempFile.Value);
}
#endregion
return result;
}
}
}
internal class Range
{
public long Start { get; set; }
public long End { get; set; }
}
public class DownloadResult
{
public long Size { get; set; }
public String FilePath { get; set; }
public TimeSpan TimeTaken { get; set; }
public int ParallelDownloads { get; set; }
public long PROGRESS { get; set; }
}
}
Để sử dụng trong form Main.cs các bạn chạy lệnh sau:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SplitDownload
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(new Action(() => {
//SplitDownload(textBox1.Text);
var result = Downloader.Download(textBox1.Text, @"", 16);
Debug.WriteLine($"=============================================================");
Debug.WriteLine($"Location: {result.FilePath}");
Debug.WriteLine($"Size: {result.Size}bytes");
Debug.WriteLine($"Time taken: {result.TimeTaken.Milliseconds}ms");
Debug.WriteLine($"Parallel: {result.ParallelDownloads}");
Debug.WriteLine($"=============================================================");
}));
}
}
}
Thanks for watching!