Skip to content

Commit

Permalink
v1.2
Browse files Browse the repository at this point in the history
重写多线程下载实现,提高稳定性
  • Loading branch information
nilaoda committed Aug 17, 2020
1 parent e35b78a commit 5a2fc70
Show file tree
Hide file tree
Showing 4 changed files with 749 additions and 673 deletions.
2 changes: 1 addition & 1 deletion BBDown/BBDown.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Version>1.1.0</Version>
<Version>1.2.0</Version>
<Description>BBDown是一个免费且便捷高效的哔哩哔哩下载/解析软件.</Description>
</PropertyGroup>

Expand Down
82 changes: 75 additions & 7 deletions BBDown/BBDownUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using static BBDown.BBDownEntity;
Expand Down Expand Up @@ -204,7 +205,28 @@ public static async Task DownloadFile(string url, string path)
}
}

public static void MultiThreadDownloadFile(string url, string path)
//https://stackoverflow.com/a/25877042
public static async Task RunWithMaxDegreeOfConcurrency<T>(
int maxDegreeOfConcurrency, IEnumerable<T> collection, Func<T, Task> taskFactory)
{
var activeTasks = new List<Task>(maxDegreeOfConcurrency);
foreach (var task in collection.Select(taskFactory))
{
activeTasks.Add(task);
if (activeTasks.Count == maxDegreeOfConcurrency)
{
await Task.WhenAny(activeTasks.ToArray());
//observe exceptions here
activeTasks.RemoveAll(t => t.IsCompleted);
}
}
await Task.WhenAll(activeTasks.ToArray()).ContinueWith(t =>
{
//observe exceptions in a manner consistent with the above
});
}

public static async Task MultiThreadDownloadFileAsync(string url, string path)
{
long fileSize = GetFileSize(url);
List<Clip> allClips = GetAllClips(url, fileSize);
Expand All @@ -213,20 +235,66 @@ public static void MultiThreadDownloadFile(string url, string path)
using (var progress = new ProgressBar())
{
progress.Report(0);
//多线程设置
await RunWithMaxDegreeOfConcurrency(8, allClips, async clip =>
{
string tmp = Path.Combine(Path.GetDirectoryName(path), clip.index.ToString("00000") + "_" + Path.GetFileNameWithoutExtension(path) + (Path.GetExtension(path).EndsWith(".mp4") ? ".vclip" : ".aclip"));
if (!(File.Exists(tmp) && new FileInfo(tmp).Length == clip.to - clip.from + 1))
{
reDown:
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0");
client.DefaultRequestHeaders.Add("Cookie", Program.COOKIE);
if (clip.to != -1)
client.DefaultRequestHeaders.Add("Range", $"bytes={clip.from}-{clip.to}");
else
client.DefaultRequestHeaders.Add("Range", $"bytes={clip.from}-");
if (!url.Contains("platform=android_tv_yst"))
client.DefaultRequestHeaders.Referrer = new Uri("https://www.bilibili.com");

var response = await client.GetAsync(url);

using (var stream = await response.Content.ReadAsStreamAsync())
{
using (var fileStream = new FileStream(tmp, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
{
var buffer = new byte[8192];
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesRead);
done += bytesRead;
progress.Report((double)done / fileSize);
}
//await stream.CopyToAsync(fileStream);
}
}
}
}
catch { goto reDown; }
}
else
{
done += new FileInfo(tmp).Length;
progress.Report((double)done / fileSize);
}
});
/*//多线程设置
ParallelOptions parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 8
};
Parallel.ForEach(allClips, parallelOptions, clip =>
Parallel.ForEach(allClips, parallelOptions, async clip =>
{
string tmp = Path.Combine(Path.GetDirectoryName(path), clip.index.ToString("00000") + "_" + Path.GetFileNameWithoutExtension(path) + (Path.GetExtension(path).EndsWith(".mp4") ? ".vclip" : ".aclip"));
if (!(File.Exists(tmp) && new FileInfo(tmp).Length == clip.to - clip.from + 1))
{
reDown:
reDown:
try
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
*//*HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Timeout = 30000;
request.ReadWriteTimeout = 30000; //重要
request.AllowAutoRedirect = true;
Expand Down Expand Up @@ -257,7 +325,7 @@ public static void MultiThreadDownloadFile(string url, string path)
}
}
}
}
}*//*
}
catch { goto reDown; }
}
Expand All @@ -266,7 +334,7 @@ public static void MultiThreadDownloadFile(string url, string path)
done += new FileInfo(tmp).Length;
progress.Report((double)done / fileSize);
}
});
});*/
}
}

Expand Down
Loading

0 comments on commit 5a2fc70

Please sign in to comment.