private static async Task DownloadFileAsync(string url, int numChunks) { using (HttpClient client = new HttpClient()) { HttpResponseMessage response = await client.GetAsync(url); response.EnsureSuccessStatusCode(); long fileSize = response.Content.Headers.ContentLength ?? 0; long chunkSize = fileSize / numChunks; long remainingBytes = fileSize; for (int i = 0; i < numChunks; i++) { long startPosition = i * chunkSize; long endPosition = (i == numChunks - 1) ? fileSize - 1 : (startPosition + chunkSize - 1); await DownloadChunkAsync(client, url, startPosition, endPosition, i); } } } private static async Task DownloadChunkAsync(HttpClient client, string url, long startPosition, long endPosition, int chunkIndex) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url); request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(startPosition, endPosition); HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); using (Stream contentStream = await response.Content.ReadAsStreamAsync()) using (FileStream fileStream = new FileStream($"chunk{chunkIndex}.dat", FileMode.Create, FileAccess.Write)) { await contentStream.CopyToAsync(fileStream); } } private static async Task CombineFileAsync(string url, int numChunks) { string outputFilePath = "output.png"; // 輸出檔案路徑 using (FileStream output = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write)) { for (int i = 0; i < numChunks; i++) { string chunkFilePath = $"chunk{i}.dat"; byte[] chunkData = File.ReadAllBytes(chunkFilePath); await output.WriteAsync(chunkData, 0, chunkData.Length); File.Delete(chunkFilePath); // 刪除合併後的片段檔案 } } }
private static async Task Main(string[] args) { { string url = "https://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024"; // 要下載的檔案 URL int numChunks = 4; // 分成的片段數量 await DownloadFileAsync(url, numChunks); await CombineFileAsync(url, numChunks); } }
首先確定要下載的檔案的大小,然後將檔案分成指定數量的塊。接著,我們針對每個塊傳送 HTTP 請求,使用 Range
頭部指定下載的範圍。每個塊的資料都將非同步寫入到一個單獨的檔案中。
最後,可以根據需要將所有塊合併成完整的檔案。
透過分片下載,我們可以同時下載多個檔案片段,以充分利用頻寬和資源,提高下載速度
首先透過 DownloadFileAsync
方法下載檔案的各個片段,然後在 CombineFileAsync
方法中將這些片段合併為一個完整的檔案。在合併檔案時,我們首先開啟一個輸出檔案流,然後逐個讀取每個片段檔案的內容並寫入輸出檔案流。最後,我們刪除了合併後不再需要的片段檔案。