mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Update vld-windows
This commit is contained in:
parent
bc02751fd5
commit
cafd260b97
@ -7,7 +7,7 @@ namespace VideoLinkDownloader.Core
|
||||
public class Video
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public int TotalSize { get; set; }
|
||||
public long TotalSize { get; set; }
|
||||
public VideoFragment[] Fragments { get; set; }
|
||||
public static (bool success, IEnumerable<Video> videos) Parse(string json)
|
||||
{
|
||||
|
||||
@ -5,6 +5,8 @@ using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace VideoLinkDownloader.Core
|
||||
{
|
||||
@ -18,13 +20,24 @@ namespace VideoLinkDownloader.Core
|
||||
{
|
||||
public Video Video { get; private set; }
|
||||
public VideoDownloaderConfig Config { get; set; } = VideoDownloaderConfig.Default;
|
||||
public ICollection<Action<double>> ProgressUpdate { get; } = new List<Action<double>>();
|
||||
public List<Action<double>> ProgressUpdate { get; } = new List<Action<double>>();
|
||||
public long DownloadedBytes
|
||||
{
|
||||
get
|
||||
{
|
||||
var entires = taskMap.ToArray();
|
||||
return entires.Select(it => it.Value).Sum();
|
||||
}
|
||||
}
|
||||
public double Progress => (double)DownloadedBytes / Video.TotalSize;
|
||||
public bool Downloading { get; private set; } = false;
|
||||
public VideoDownloader(Video video)
|
||||
{
|
||||
Video = video;
|
||||
}
|
||||
public async Task<IEnumerable<VideoDownloadResult>> Download()
|
||||
{
|
||||
taskMap = new Dictionary<Task, long>();
|
||||
var results = await Task.WhenAll(from fragment in Video.Fragments select downloadFragment(fragment));
|
||||
await Task.WhenAll(from fragment in Video.Fragments select mergeParts(fragment));
|
||||
return results;
|
||||
@ -33,10 +46,10 @@ namespace VideoLinkDownloader.Core
|
||||
{
|
||||
return Video.Fragments.Length == 1 ? Video.Title : $"{Video.Title} - {Array.IndexOf(Video.Fragments, fragment) + 1}";
|
||||
}
|
||||
private Dictionary<Task, double> taskMap = new Dictionary<Task, double>();
|
||||
private Dictionary<Task, long> taskMap = new Dictionary<Task, long>();
|
||||
private void updateProgress()
|
||||
{
|
||||
|
||||
ProgressUpdate.ForEach(it => it(Progress));
|
||||
}
|
||||
private async Task<VideoDownloadResult> downloadFragment(VideoFragment fragment)
|
||||
{
|
||||
@ -49,7 +62,6 @@ namespace VideoLinkDownloader.Core
|
||||
}
|
||||
var startByte = 0;
|
||||
var part = 0;
|
||||
taskMap = new Dictionary<Task, double>();
|
||||
while (startByte < fragment.Size)
|
||||
{
|
||||
var partFilename = $"{title}.part{part}";
|
||||
@ -57,34 +69,51 @@ namespace VideoLinkDownloader.Core
|
||||
{
|
||||
var endByte = Math.Min(fragment.Size, startByte + partialLength) - 1;
|
||||
var range = $"bytes={startByte}-{endByte}";
|
||||
using (var webclient = new WebClient())
|
||||
var client = new HttpClient();
|
||||
client.DefaultRequestHeaders.Range = new RangeHeaderValue(startByte, endByte);
|
||||
client.DefaultRequestHeaders.Referrer = new Uri("https://www.bilibili.com", UriKind.Absolute);
|
||||
client.DefaultRequestHeaders.Add("Origin", "https://www.bilibili.com");
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36");
|
||||
//client.Headers[HttpRequestHeader.Range] = range;
|
||||
//client.Headers[HttpRequestHeader.Referer] = "https://www.bilibili.com";
|
||||
//client.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36";
|
||||
//client.Headers["Origin"] = "https://www.bilibili.com";
|
||||
Task task = null;
|
||||
try
|
||||
{
|
||||
webclient.Headers[HttpRequestHeader.Range] = range;
|
||||
webclient.Headers[HttpRequestHeader.Referer] = "https://www.bilibili.com";
|
||||
webclient.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36";
|
||||
webclient.Headers["Origin"] = "https://www.bilibili.com";
|
||||
Task task = null;
|
||||
try
|
||||
task = Task.Run(async () =>
|
||||
{
|
||||
task = webclient.DownloadFileTaskAsync(fragment.Url, partFilename);
|
||||
webclient.DownloadProgressChanged += (s, e) =>
|
||||
using (var response = await client.GetStreamAsync(fragment.Url))
|
||||
using (var file = File.OpenWrite(partFilename))
|
||||
{
|
||||
taskMap[task] = e.BytesReceived;
|
||||
};
|
||||
taskMap.Add(task, 0.0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is WebException || ex is InvalidOperationException)
|
||||
{
|
||||
// TODO: handle web errors
|
||||
return VideoDownloadResult.Failed;
|
||||
}
|
||||
while (response.CanRead)
|
||||
{
|
||||
file.WriteByte((byte)response.ReadByte());
|
||||
taskMap[task]++;
|
||||
updateProgress();
|
||||
}
|
||||
}
|
||||
});
|
||||
//task = client.DownloadFileTaskAsync(fragment.Url, partFilename);
|
||||
//client.DownloadProgressChanged += (s, e) =>
|
||||
//{
|
||||
// taskMap[task] = e.BytesReceived;
|
||||
//};
|
||||
taskMap.Add(task, 0L);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is WebException || ex is InvalidOperationException)
|
||||
{
|
||||
// TODO: handle web errors
|
||||
return VideoDownloadResult.Failed;
|
||||
}
|
||||
}
|
||||
part++;
|
||||
startByte = startByte + partialLength;
|
||||
}
|
||||
Downloading = true;
|
||||
await Task.WhenAll(taskMap.Select(it => it.Key));
|
||||
Downloading = false;
|
||||
return VideoDownloadResult.Success;
|
||||
}
|
||||
private async Task mergeParts(VideoFragment fragment)
|
||||
|
||||
@ -4,4 +4,8 @@
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
<ResourceDictionary
|
||||
Source="Theme.Dark.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<SolidColorBrush
|
||||
x:Key="ThemeColor"
|
||||
Color="#26a69a" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@ -15,7 +15,8 @@ namespace VideoLinkDownloader
|
||||
{
|
||||
base.OnStartup(e);
|
||||
var registry = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
|
||||
if (registry is null || (int) registry.GetValue("AppsUseLightTheme", 0) == 1)
|
||||
// if (registry is null || (int) registry.GetValue("AppsUseLightTheme", 0) == 1)
|
||||
if (true)
|
||||
{
|
||||
Resources.MergedDictionaries.Remove(new ResourceDictionary
|
||||
{
|
||||
|
||||
32
extras/vld-windows/VideoLinkDownloader/Extensions.cs
Normal file
32
extras/vld-windows/VideoLinkDownloader/Extensions.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VideoLinkDownloader
|
||||
{
|
||||
static class Extensions
|
||||
{
|
||||
public static string ToFileSize(this long size)
|
||||
{
|
||||
string[] units = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
|
||||
if (size == 0)
|
||||
{
|
||||
return "0" + units[0];
|
||||
}
|
||||
|
||||
var bytes = Math.Abs(size);
|
||||
var place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
|
||||
var num = Math.Round(bytes / Math.Pow(1024, place), 1);
|
||||
return (Math.Sign(size) * num).ToString() + units[place];
|
||||
}
|
||||
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
|
||||
{
|
||||
foreach (var item in collection)
|
||||
{
|
||||
action(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,9 +8,10 @@
|
||||
mc:Ignorable="d"
|
||||
Background="{DynamicResource Background}"
|
||||
Foreground="{DynamicResource Foreground}"
|
||||
Title="MainWindow"
|
||||
Height="450"
|
||||
Width="800">
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Title="Bilibili Evolved Video Link Downloader"
|
||||
Height="800"
|
||||
Width="600">
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome
|
||||
GlassFrameThickness="1"
|
||||
|
||||
@ -11,6 +11,59 @@
|
||||
Title="MainPage">
|
||||
|
||||
<Grid>
|
||||
|
||||
<ItemsControl
|
||||
Margin="30"
|
||||
ItemsSource="{Binding VideoTasks}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="6*" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.Resources>
|
||||
<Style
|
||||
TargetType="TextBlock">
|
||||
<Setter
|
||||
Property="Foreground"
|
||||
Value="{StaticResource Foreground}" />
|
||||
<Setter
|
||||
Property="HorizontalAlignment"
|
||||
Value="Center" />
|
||||
<Setter
|
||||
Property="VerticalAlignment"
|
||||
Value="Center" />
|
||||
<Setter
|
||||
Property="TextWrapping"
|
||||
Value="Wrap" />
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<TextBlock
|
||||
Text="{Binding Title}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Text="{Binding PercentProgress}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Text="{Binding SizeProgress}" />
|
||||
<ProgressBar
|
||||
Grid.Row="1"
|
||||
Maximum="1"
|
||||
Minimum="0"
|
||||
Height="2"
|
||||
Margin="12,0"
|
||||
BorderThickness="0"
|
||||
Background="#4888"
|
||||
Foreground="{StaticResource ThemeColor}"
|
||||
Value="{Binding Progress}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@ -12,17 +12,16 @@ using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using VideoLinkDownloader.Pages.Main;
|
||||
|
||||
namespace VideoLinkDownloader.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// MainPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainPage : Page
|
||||
{
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new MainPageViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using VideoLinkDownloader.Core;
|
||||
|
||||
namespace VideoLinkDownloader.Pages.Main
|
||||
{
|
||||
class MainPageViewModel : NotificationObject
|
||||
{
|
||||
|
||||
public MainPageViewModel()
|
||||
{
|
||||
if (Clipboard.ContainsText())
|
||||
{
|
||||
var text = Clipboard.GetText();
|
||||
var (success, videos) = Video.Parse(text);
|
||||
if (success)
|
||||
{
|
||||
videos.ForEach(video => VideoTasks.Add(new VideoTask(video)));
|
||||
}
|
||||
}
|
||||
VideoTasks.ForEach(async it => await it.Download());
|
||||
}
|
||||
public ObservableCollection<VideoTask> VideoTasks { get; } = new ObservableCollection<VideoTask>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,8 +41,12 @@
|
||||
<ApplicationIcon>Bilibili-Evolved.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
@ -61,6 +65,8 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="VideoTask.cs" />
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -84,9 +90,11 @@
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="NotificationObject.cs" />
|
||||
<Compile Include="Pages\Main\MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\Main\MainPageViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
@ -104,6 +112,7 @@
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
||||
@ -12,6 +12,10 @@ namespace VideoLinkDownloader
|
||||
public VideoTask(Video video)
|
||||
{
|
||||
Downloader = new VideoDownloader(video);
|
||||
Downloader.ProgressUpdate.Add(progress =>
|
||||
{
|
||||
Progress = progress;
|
||||
});
|
||||
}
|
||||
public VideoDownloader Downloader { get; private set; }
|
||||
|
||||
@ -23,8 +27,12 @@ namespace VideoLinkDownloader
|
||||
{
|
||||
progress = value;
|
||||
OnPropertyChanged(nameof(Progress));
|
||||
OnPropertyChanged(nameof(SizeProgress));
|
||||
}
|
||||
}
|
||||
public string Title => Downloader.Video.Title;
|
||||
public string PercentProgress => $"{Math.Floor(Progress * 1000) / 10}%";
|
||||
public string SizeProgress => $"{Downloader.DownloadedBytes.ToFileSize()} / {Downloader.Video.TotalSize.ToFileSize()}";
|
||||
public async Task Download()
|
||||
{
|
||||
await Downloader.Download();
|
||||
|
||||
4
extras/vld-windows/VideoLinkDownloader/packages.config
Normal file
4
extras/vld-windows/VideoLinkDownloader/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
|
||||
</packages>
|
||||
Loading…
Reference in New Issue
Block a user