I'm reusing HttpClient
for all my download task because I always saw in SO that I should reuse httpclient for everything. But I'm getting this exception Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The request was aborted: The request was canceled.
This is the things I've done so far.
1. Make new instance of HttpClient for every download task (worked, but not reusing the httpclient)
2. Reduce the number of task to 2 (works, anything above 2 throws an exception)
3. Remove HttpCompletionOption.ResponseHeadersRead
from request message (works, but it takes too long to start the download, I think it continue to read all files before starting the stream)
4. Make HttpClient
timeout to infinite (didn't work)
5. Make used of HttpContent.ReadAsStreamAsync
method and set read timeout to infinite (didn't work)
Here is the code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Task.Run(() => new Downloader().Download(
"https://ia800703.us.archive.org/34/items/1mbFile/1mb.mp4",
"1mb.mp4"
)).Wait();
}
}
public class Downloader
{
HttpClient httpClient;
public Downloader()
{
httpClient = new HttpClient();
}
public async Task Download(string url, string saveAs)
{
var response = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, url), HttpCompletionOption.ResponseHeadersRead);
var parallelDownloadSuported = response.Headers.AcceptRanges.Contains("bytes");
var contentLength = response.Content.Headers.ContentLength ?? 0;
if (parallelDownloadSuported)
{
const double numberOfParts = 5.0;
var tasks = new List<Task>();
var partSize = (long)Math.Ceiling(contentLength / numberOfParts);
File.Create(saveAs).Dispose();
for (var i = 0; i < numberOfParts; i++)
{
var start = i * partSize + Math.Min(1, i);
var end = Math.Min((i + 1) * partSize, contentLength);
tasks.Add(
Task.Run(() => DownloadPart(url, saveAs, start, end))
);
}
await Task.WhenAll(tasks);
}
}
private async void DownloadPart(string url, string saveAs, long start, long end)
{
using (var fileStream = new FileStream(saveAs, FileMode.Open, FileAccess.Write, FileShare.Write, 1024, true))
{
var message = new HttpRequestMessage(HttpMethod.Get, url);
message.Headers.Add("Range", string.Format("bytes={0}-{1}", start, end));
fileStream.Position = start;
await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead).Result.Content.CopyToAsync(fileStream);
}
}
}
}
codes are from :here