KKrzysztof KrysińskiAdded download progress bar
58c5f424创建于 2025年5月29日历史提交
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace PixiEditor.UpdateModule;

public static class UpdateDownloader
{
    public static string DownloadLocation { get; } = Path.Join(Path.GetTempPath(), "PixiEditor");

    public static event Action<double> ProgressChanged;

    public static async Task DownloadReleaseZip(ReleaseInfo release, string contentType, string extension)
    {
        Asset? matchingAsset = GetMatchingAsset(release, contentType);

        if (matchingAsset == null)
        {
            throw new FileNotFoundException("No matching update for your system found.");
        }

        using WebClient client = new WebClient();
        client.Headers.Add("User-Agent", "PixiEditor");
        client.Headers.Add("Accept", "application/octet-stream");
        client.DownloadProgressChanged += (sender, args) =>
        {
            ProgressChanged?.Invoke(args.ProgressPercentage);
        };

        var bytes = await client.DownloadDataTaskAsync(matchingAsset.Url);
        CreateTempDirectory();
        await File.WriteAllBytesAsync(Path.Join(DownloadLocation, $"update-{release.TagName}.{extension}"), bytes);
    }

    public static async Task DownloadInstaller(ReleaseInfo info)
    {
        Asset? matchingAsset = GetMatchingAsset(info, "application/x-msdownload");

        if (matchingAsset == null)
        {
            throw new FileNotFoundException("No matching update for your system found.");
        }

        using HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Add("User-Agent", "PixiEditor");
        client.DefaultRequestHeaders.Add("Accept", "application/octet-stream");
        var response = await client.GetAsync(matchingAsset.Url);
        if (response.StatusCode == HttpStatusCode.OK)
        {
            byte[] bytes = await response.Content.ReadAsByteArrayAsync();
            CreateTempDirectory();
            await File.WriteAllBytesAsync(Path.Join(DownloadLocation, $"update-{info.TagName}.exe"), bytes);
        }
    }

    public static void CreateTempDirectory()
    {
        if (!Directory.Exists(DownloadLocation))
        {
            Directory.CreateDirectory(DownloadLocation);
        }
    }

    private static Asset? GetMatchingAsset(ReleaseInfo release, string assetType)
    {
        if (release.TagName.StartsWith("1."))
        {
            string archOld = IntPtr.Size == 8 ? "x64" : "x86";
            return release.Assets.FirstOrDefault(x => x.ContentType.Contains(assetType)
                                                      && x.Name.Contains(archOld));
        }

        string arch = OperatingSystem.IsWindows() ? "x64" :
            OperatingSystem.IsLinux() ? "amd64" : "universal";
        string os = OperatingSystem.IsWindows() ? "win" : OperatingSystem.IsLinux() ? "linux" : "macos";
        return release.Assets.FirstOrDefault(x => x.ContentType.Contains(assetType)
                                                  && x.Name.Contains(arch) && x.Name.Contains(os));
    }
}