连续20秒速度为0时,重试

This commit is contained in:
nilaoda 2022-09-25 10:41:41 +08:00
parent b032b46bd3
commit 9211e185fd
5 changed files with 70 additions and 29 deletions

View File

@ -32,7 +32,7 @@ namespace N_m3u8DL_RE.Common.Util
public static readonly HttpClient AppHttpClient = new(HttpClientHandler)
{
Timeout = TimeSpan.FromMinutes(2)
Timeout = TimeSpan.FromSeconds(100)
};
private static async Task<HttpResponseMessage> DoGetAsync(string url, Dictionary<string, string>? headers = null)

View File

@ -13,10 +13,11 @@ namespace N_m3u8DL_RE.Column
{
internal sealed class DownloadSpeedColumn : ProgressColumn
{
private long _stopSpeed = 0;
private ConcurrentDictionary<int, string> DateTimeStringDic = new();
private ConcurrentDictionary<int, string> SpeedDic = new();
protected override bool NoWrap => true;
public ConcurrentDictionary<int, SpeedContainer> SpeedContainerDic { get; set; }
private ConcurrentDictionary<int, SpeedContainer> SpeedContainerDic { get; set; }
public DownloadSpeedColumn(ConcurrentDictionary<int, SpeedContainer> SpeedContainerDic)
{
@ -38,9 +39,12 @@ namespace N_m3u8DL_RE.Column
task.Value = speedContainer.RDownloaded;
}
//一秒汇报一次即可
if (DateTimeStringDic.TryGetValue(taskId, out var oldTime) && oldTime != now)
if (DateTimeStringDic.TryGetValue(taskId, out var oldTime) && oldTime != now)
{
SpeedDic[taskId] = FormatFileSize(speedContainer.Downloaded);
//速度为0计数增加
if (speedContainer.Downloaded <= _stopSpeed) { speedContainer.AddLowSpeedCount(); SpeedDic[taskId] += $"({speedContainer.LowSpeedCount})"; }
else speedContainer.ResetLowSpeedCount();
speedContainer.Reset();
}
DateTimeStringDic[taskId] = now;

View File

@ -406,7 +406,7 @@ namespace N_m3u8DL_RE.CommandLine
Environment.Exit(0);
}
var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220922")
var rootCommand = new RootCommand("N_m3u8DL-RE (Beta version) 20220925")
{
Input, TmpDir, SaveDir, SaveName, BaseUrl, ThreadCount, DownloadRetryCount, AutoSelect, SkipMerge, SkipDownload, CheckSegmentsCount,
BinaryMerge, DelAfterDone, WriteMetaJson, AppendUrlParams, ConcurrentDownload, Headers, /**SavePattern,**/ SubOnly, SubtitleFormat, AutoSubtitleFix,

View File

@ -14,12 +14,25 @@ namespace N_m3u8DL_RE.Entity
public bool SingleSegment { get; set; } = false;
public long? ResponseLength { get; set; }
public long RDownloaded { get; set; } = 0L;
private int _zeroSpeedCount = 0;
public int LowSpeedCount { get => _zeroSpeedCount; }
public bool ShouldStop { get => LowSpeedCount >= 20; }
///////////////////////////////////////////////////
private long _downloaded = 0;
public long Downloaded { get => _downloaded; }
public int AddLowSpeedCount()
{
return Interlocked.Add(ref _zeroSpeedCount, 1);
}
public int ResetLowSpeedCount()
{
return Interlocked.Exchange(ref _zeroSpeedCount, 0);
}
public long Add(long size)
{
if (SingleSegment) RDownloaded += size;
@ -34,6 +47,7 @@ namespace N_m3u8DL_RE.Entity
public void ResetVars()
{
Reset();
ResetLowSpeedCount();
SingleSegment = false;
ResponseLength = null;
RDownloaded = 0L;

View File

@ -31,37 +31,60 @@ namespace N_m3u8DL_RE.Util
}
}
Logger.Debug(request.Headers.ToString());
using var response = await AppHttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.StatusCode == HttpStatusCode.Found || response.StatusCode == HttpStatusCode.Moved)
CancellationTokenSource cancellationTokenSource = new(); //取消下载
using var watcher = Task.Factory.StartNew(async () =>
{
HttpResponseHeaders respHeaders = response.Headers;
Logger.Debug(respHeaders.ToString());
if (respHeaders != null && respHeaders.Location != null)
while (true)
{
var redirectedUrl = respHeaders.Location.AbsoluteUri;
return await DownloadToFileAsync(redirectedUrl, path, speedContainer, headers, fromPosition, toPosition);
if (speedContainer == null) break;
if (speedContainer.ShouldStop)
{
cancellationTokenSource.Cancel();
speedContainer.ResetLowSpeedCount();
Logger.WarnMarkUp("Cancel...");
break;
}
await Task.Delay(500);
}
}
response.EnsureSuccessStatusCode();
var contentLength = response.Content.Headers.ContentLength;
if (speedContainer.SingleSegment) speedContainer.ResponseLength = contentLength;
using var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
using var responseStream = await response.Content.ReadAsStreamAsync();
var buffer = new byte[16 * 1024];
var size = 0;
while ((size = await responseStream.ReadAsync(buffer)) > 0)
});
try
{
speedContainer.Add(size);
await stream.WriteAsync(buffer, 0, size);
}
using var response = await AppHttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token);
if (response.StatusCode == HttpStatusCode.Found || response.StatusCode == HttpStatusCode.Moved)
{
HttpResponseHeaders respHeaders = response.Headers;
Logger.Debug(respHeaders.ToString());
if (respHeaders != null && respHeaders.Location != null)
{
var redirectedUrl = respHeaders.Location.AbsoluteUri;
return await DownloadToFileAsync(redirectedUrl, path, speedContainer, headers, fromPosition, toPosition);
}
}
response.EnsureSuccessStatusCode();
var contentLength = response.Content.Headers.ContentLength;
if (speedContainer.SingleSegment) speedContainer.ResponseLength = contentLength;
return new DownloadResult()
using var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
using var responseStream = await response.Content.ReadAsStreamAsync(cancellationTokenSource.Token);
var buffer = new byte[16 * 1024];
var size = 0;
while ((size = await responseStream.ReadAsync(buffer, cancellationTokenSource.Token)) > 0)
{
speedContainer.Add(size);
await stream.WriteAsync(buffer, 0, size);
}
return new DownloadResult()
{
ActualContentLength = stream.Length,
RespContentLength = contentLength,
ActualFilePath = path
};
}
catch (OperationCanceledException oce) when (oce.CancellationToken == cancellationTokenSource.Token)
{
ActualContentLength = stream.Length,
RespContentLength = contentLength,
ActualFilePath = path
};
throw new Exception("Download speed too slow!");
}
}
}
}