Skip to content

Commit

Permalink
Merge pull request #5 from YPermitin/develop
Browse files Browse the repository at this point in the history
Улучшен функционал загрузки дистрибутивов ФИАС
  • Loading branch information
YPermitin authored Jul 6, 2023
2 parents b89127d + 4dfae48 commit 8cc8188
Show file tree
Hide file tree
Showing 16 changed files with 441 additions and 44 deletions.
47 changes: 47 additions & 0 deletions Apps/YPermitin.FIASToolSet.DistributionDownloader/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// See https://aka.ms/new-console-template for more information

using YPermitin.FIASToolSet.DistributionBrowser;
using YPermitin.FIASToolSet.DistributionBrowser.Enums;
using YPermitin.FIASToolSet.DistributionBrowser.Models;

Console.WriteLine("Тестовая загрузка полного дистрибутива ФИАС.");

IFIASDistributionBrowser loader = new FIASDistributionBrowser();
var lastInfo = await loader.GetLastDistributionInfo();
var xmlFullUrl = lastInfo?.GetUrlByFileType(DistributionFileType.GARFIASXmlComplete);

var tempFileToDownload = Path.Combine(
Path.GetTempPath(),
"FIAS_FULL.zip");

DateTime downloadStarted = DateTime.UtcNow;
DateTime lastProgressShow = DateTime.MinValue;
double lastProgressPercentage = 0;
await lastInfo?.DownloadDistributionByFileTypeAsync(
DistributionFileType.GARFIASXmlComplete,
tempFileToDownload,
(args) =>
{
double progress = Math.Round(args.ProgressPercentage, 2);
double progressChanged = lastProgressPercentage - progress;
var showProgressTimeLeft = DateTime.UtcNow - lastProgressShow;
if (args.State != DownloadDistributionFileProgressChangedEventType.Downloading
|| showProgressTimeLeft.TotalSeconds > 10
|| progressChanged >= 1)
{
var downloadDuration = DateTime.UtcNow - downloadStarted;
Console.WriteLine($"[{DateTime.UtcNow}] {args.State}. Progress: {progress} %. Seconds left: {downloadDuration.TotalSeconds}");
if (args.ErrorInfo != null)
{
Console.WriteLine(args.ErrorInfo.GetBaseException().Message);
}
lastProgressPercentage = progress;
lastProgressShow = DateTime.UtcNow;
}
});

Console.WriteLine("Для выхода нажмите любую клавишу...");
Console.ReadKey();
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Libs\YPermitin.FIASToolSet.DistributionBrowser\YPermitin.FIASToolSet.DistributionBrowser.csproj" />
</ItemGroup>

</Project>
88 changes: 58 additions & 30 deletions Libs/YPermitin.FIASToolSet.DistributionBrowser/API/APIHelper.cs
Original file line number Diff line number Diff line change
@@ -1,52 +1,80 @@
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Downloader;
using YPermitin.FIASToolSet.DistributionBrowser.Models;

namespace YPermitin.FIASToolSet.DistributionBrowser.API
{
internal class APIHelper : IAPIHelper
{
private readonly HttpClient _apiClient;


public APIHelper()
private static readonly string DefaultUserAgent = GeneralResources.DefaultUserAgent;
private static readonly HttpClient APIClient;
private static readonly DownloadConfiguration DownloaderConfiguration = new DownloadConfiguration()
{
_apiClient = new HttpClient();
ChunkCount = 8,
ParallelDownload = true,
RequestConfiguration = new RequestConfiguration()
{
UserAgent = DefaultUserAgent
}
};
static APIHelper()
{
APIClient = new HttpClient();
APIClient.DefaultRequestHeaders
.UserAgent.TryParseAdd(DefaultUserAgent);
}

/// <summary>
/// Загрузка файла по URL и сохранение его в файловой системе
/// </summary>
/// <param name="uriFile">URL файла</param>
/// <param name="savePath">Путь для сохранения</param>
/// <param name="onDownloadFileProgressChangedEvent">Событие с информацией о прогрессе загрузки файла</param>
/// <returns>Асинхронная операция</returns>
public async Task DownloadFileAsync(Uri uriFile, string savePath)
public async Task DownloadFileAsync(Uri uriFile, string savePath,
Action<DownloadDistributionFileProgressChangedEventArgs> onDownloadFileProgressChangedEvent = null)
{
using (HttpResponseMessage response = _apiClient.GetAsync(uriFile, HttpCompletionOption.ResponseHeadersRead).Result)
var downloader = new DownloadService(DownloaderConfiguration);
downloader.DownloadStarted += (sender, args) =>
{
response.EnsureSuccessStatusCode();

await using (Stream contentStream = await response.Content.ReadAsStreamAsync(), fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
var eventArgs = new DownloadDistributionFileProgressChangedEventArgs(
state: DownloadDistributionFileProgressChangedEventType.Started,
progressPercentage: 0);
onDownloadFileProgressChangedEvent?.Invoke(eventArgs);
};
downloader.DownloadProgressChanged += (sender, args) =>
{
var eventArgs = new DownloadDistributionFileProgressChangedEventArgs(
state: DownloadDistributionFileProgressChangedEventType.Downloading,
progressPercentage: args.ProgressPercentage);
onDownloadFileProgressChangedEvent?.Invoke(eventArgs);
};
downloader.DownloadFileCompleted += (sender, args) =>
{
DownloadDistributionFileProgressChangedEventType state;
Exception errorInfo = null;
if (args.Cancelled)
state = DownloadDistributionFileProgressChangedEventType.Canceled;
else if (args.Error != null)
{
var buffer = new byte[8192];
var isMoreToRead = true;

do
{
var read = await contentStream.ReadAsync(buffer, 0, buffer.Length);
if (read == 0)
{
isMoreToRead = false;
}
else
{
await fileStream.WriteAsync(buffer, 0, read);
}
}
while (isMoreToRead);
state = DownloadDistributionFileProgressChangedEventType.Failure;
errorInfo = args.Error;
}
}
else
{
state = DownloadDistributionFileProgressChangedEventType.Compleated;
}
var eventArgs = new DownloadDistributionFileProgressChangedEventArgs(
state: state,
progressPercentage: 100,
errorInfo: errorInfo);
onDownloadFileProgressChangedEvent?.Invoke(eventArgs);
};
await downloader.DownloadFileTaskAsync(uriFile.AbsoluteUri, savePath);
}

/// <summary>
Expand All @@ -56,7 +84,7 @@ public async Task DownloadFileAsync(Uri uriFile, string savePath)
/// <returns>Строкове содержимое данных по URL</returns>
public async Task<string> GetContentAsStringAsync(Uri uri)
{
var response = await _apiClient.GetAsync(uri);
var response = await APIClient.GetAsync(uri);
response.EnsureSuccessStatusCode();

var content = await response.Content.ReadAsStringAsync();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using YPermitin.FIASToolSet.DistributionBrowser.Models;

namespace YPermitin.FIASToolSet.DistributionBrowser.API
{
Expand All @@ -10,8 +11,10 @@ internal interface IAPIHelper
/// </summary>
/// <param name="uriFile">URL файла</param>
/// <param name="savePath">Путь для сохранения</param>
/// <param name="onDownloadFileProgressChangedEvent">Событие с информацией о прогрессе загрузки файла</param>
/// <returns>Асинхронная операция</returns>
Task DownloadFileAsync(Uri uriFile, string savePath);
Task DownloadFileAsync(Uri uriFile, string savePath,
Action<DownloadDistributionFileProgressChangedEventArgs> onDownloadFileProgressChangedEvent = null);

/// <summary>
/// Получение содержимого по URL
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace YPermitin.FIASToolSet.DistributionBrowser.Enums;

/// <summary>
/// Типы файлов дистрибутива ФИАС для загрузки
/// </summary>
public enum DistributionFileType
{
FIASDbfComplete,
FIASDbfDelta,
FIASXmlComplete,
FIASXmlDelta,
GARFIASXmlComplete,
GARFIASXmlDelta,
KLADR4ArjComplete,
KLADR47zComplete
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>

<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">

</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="DefaultUserAgent" xml:space="preserve">
<value>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 YaBrowser/23.5.1.800 Yowser/2.5 Safari/537.36</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace YPermitin.FIASToolSet.DistributionBrowser.Models;

public class DownloadDistributionFileProgressChangedEventArgs
{
public DownloadDistributionFileProgressChangedEventType State { get; }
public double ProgressPercentage { get; }
public Exception ErrorInfo { get; }

public DownloadDistributionFileProgressChangedEventArgs(
DownloadDistributionFileProgressChangedEventType state,
double progressPercentage,
Exception errorInfo = null)
{
ProgressPercentage = progressPercentage;
State = state;
ErrorInfo = errorInfo;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace YPermitin.FIASToolSet.DistributionBrowser.Models;

public enum DownloadDistributionFileProgressChangedEventType
{
Started,
Downloading,
Compleated,
Failure,
Canceled
}
Loading

0 comments on commit 8cc8188

Please sign in to comment.