rdt-client/server/RdtClient.Service/Services/DownloadClient.cs
2021-02-09 19:56:24 -07:00

226 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using Downloader;
using RdtClient.Data.Models.Data;
using RdtClient.Service.Helpers;
namespace RdtClient.Service.Services
{
public class DownloadClient
{
private readonly String _destinationPath;
private readonly Download _download;
private readonly Torrent _torrent;
private DownloadService _downloader;
private SimpleDownloader _simpleDownloader;
public DownloadClient(Download download, String destinationPath)
{
_download = download;
_destinationPath = destinationPath;
_torrent = download.Torrent;
}
public Boolean Finished { get; private set; }
public String Error { get; private set; }
public Int64 Speed { get; private set; }
public Int64 BytesTotal { get; private set; }
public Int64 BytesDone { get; private set; }
public async Task Start(IList<Setting> settings)
{
BytesDone = 0;
BytesTotal = 0;
Speed = 0;
try
{
var downloadClientSetting = settings.GetString("DownloadClient");
var fileUrl = _download.Link;
if (String.IsNullOrWhiteSpace(fileUrl))
{
throw new Exception("File URL is empty");
}
var uri = new Uri(fileUrl);
var torrentPath = Path.Combine(_destinationPath, _torrent.RdName);
if (!Directory.Exists(torrentPath))
{
Directory.CreateDirectory(torrentPath);
}
var fileName = uri.Segments.Last();
fileName = HttpUtility.UrlDecode(fileName);
var filePath = Path.Combine(torrentPath, fileName);
if (File.Exists(filePath))
{
File.Delete(filePath);
}
await Task.Factory.StartNew(async delegate
{
switch (downloadClientSetting)
{
case "Simple":
await DownloadSimple(uri, filePath);
break;
case "MultiPart":
await DownloadMultiPart(filePath, settings);
break;
default:
throw new Exception($"Unknown download client {downloadClientSetting}");
}
});
}
catch (Exception ex)
{
Error = $"An unexpected error occurred preparing download {_download.Link} for torrent {_torrent.RdName}: {ex.Message}";
Finished = true;
}
}
public void Cancel()
{
_downloader?.CancelAsync();
_simpleDownloader?.Cancel();
}
private async Task DownloadSimple(Uri uri, String filePath)
{
try
{
_simpleDownloader = new SimpleDownloader();
_simpleDownloader.DownloadProgressChanged += (_, args) =>
{
Speed = (Int64) args.BytesPerSecondSpeed;
BytesDone = args.ReceivedBytesSize;
BytesTotal = args.TotalBytesToReceive;
};
_simpleDownloader.DownloadFileCompleted += (_, args) =>
{
if (args.Cancelled)
{
Error = $"The download was cancelled";
}
else if (args.Error != null)
{
Error = args.Error.Message;
}
Finished = true;
};
Speed = 0;
BytesDone = 0;
BytesTotal = 0;
await _simpleDownloader.Download(uri, filePath);
}
catch (Exception ex)
{
Error = $"An unexpected error occurred downloading {_download.Link} for torrent {_torrent.RdName}: {ex.Message}";
Finished = true;
}
}
private async Task DownloadMultiPart(String filePath, IList<Setting> settings)
{
try
{
var settingTempPath = settings.GetString("TempPath");
if (String.IsNullOrWhiteSpace(settingTempPath))
{
settingTempPath = Path.GetTempPath();
}
var settingDownloadChunkCount = settings.GetNumber("DownloadChunkCount");
if (settingDownloadChunkCount <= 0)
{
settingDownloadChunkCount = 1;
}
var settingDownloadMaxSpeed = settings.GetNumber("DownloadMaxSpeed");
if (settingDownloadMaxSpeed <= 0)
{
settingDownloadMaxSpeed = 0;
}
settingDownloadMaxSpeed = settingDownloadMaxSpeed * 1024 * 1024;
var settingProxyServer = settings.GetString("ProxyServer");
var downloadOpt = new DownloadConfiguration
{
MaxTryAgainOnFailover = Int32.MaxValue,
ParallelDownload = settingDownloadChunkCount > 1,
ChunkCount = settingDownloadChunkCount,
Timeout = 1000,
OnTheFlyDownload = false,
BufferBlockSize = 1024 * 8,
MaximumBytesPerSecond = settingDownloadMaxSpeed,
TempDirectory = settingTempPath,
RequestConfiguration =
{
Accept = "*/*",
UserAgent = $"rdt-client",
ProtocolVersion = HttpVersion.Version11,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
KeepAlive = true,
UseDefaultCredentials = false
}
};
if (!String.IsNullOrWhiteSpace(settingProxyServer))
{
downloadOpt.RequestConfiguration.Proxy = new WebProxy(new Uri(settingProxyServer), false);
}
_downloader = new DownloadService(downloadOpt);
_downloader.DownloadProgressChanged += (_, args) =>
{
Speed = (Int64) args.BytesPerSecondSpeed;
BytesDone = args.ReceivedBytesSize;
BytesTotal = args.TotalBytesToReceive;
};
_downloader.DownloadFileCompleted += (_, args) =>
{
if (args.Cancelled)
{
Error = $"The download was cancelled";
}
else if (args.Error != null)
{
Error = args.Error.Message;
}
Finished = true;
};
await _downloader.DownloadFileAsync(_download.Link, filePath);
}
catch (Exception ex)
{
Error = $"An unexpected error occurred downloading {_download.Link} for torrent {_torrent.RdName}: {ex.Message}";
Finished = true;
}
}
}
}