Я повторно использую HttpClient
для всех своих задач загрузки, потому что я всегда видел в SO, что мне следует повторно использовать httpclient для всего. Но я получаю это исключение 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.
Это то, что я сделал до сих пор.
1. Создайте новый экземпляр HttpClient для каждой задачи загрузки (работал, но не повторно использовал httpclient)
2. Уменьшить количество заданий до 2 (работает, все, что выше 2, вызывает исключение)
3. Удалите HttpCompletionOption.ResponseHeadersRead
из сообщения запроса (работает, но для начала загрузки требуется слишком много времени, я думаю, что он продолжает читать все файлы перед запуском потока)
4. Сделать HttpClient
тайм-аут до бесконечности (не работает)
5. Используйте метод HttpContent.ReadAsStreamAsync
и установите время ожидания чтения на бесконечное (не работает)
Вот код
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);
}
}
}
}
коды от: здесь