diff --git a/server/RdtClient.Data/Models/Internal/DbSettings.cs b/server/RdtClient.Data/Models/Internal/DbSettings.cs index 71fed49..68cae34 100644 --- a/server/RdtClient.Data/Models/Internal/DbSettings.cs +++ b/server/RdtClient.Data/Models/Internal/DbSettings.cs @@ -119,6 +119,10 @@ http://127.0.0.1:6800/jsonrpc.")] [DisplayName("Aria2c Secret (only used for the Aria2c Downloader)")] [Description("The secret of your Aria2c instance. Optional.")] public String Aria2cSecret { get; set; } = "mysecret123"; + + [DisplayName("Aria2c Download Path")] + [Description("The root path to download the file to on the Aria2c host, if empty use the Download path setting.")] + public String? Aria2cDownloadPath { get; set; } = null; [DisplayName("Rclone mount path (only used for the Symlink Downloader)")] [Description("Path where Rclone is mounted. Required for Symlink Downloader.")] diff --git a/server/RdtClient.Service/Helpers/DownloadHelper.cs b/server/RdtClient.Service/Helpers/DownloadHelper.cs index e6a5966..7630f4e 100644 --- a/server/RdtClient.Service/Helpers/DownloadHelper.cs +++ b/server/RdtClient.Service/Helpers/DownloadHelper.cs @@ -35,6 +35,34 @@ public static class DownloadHelper return filePath; } + public static String? GetDownloadPath(Torrent torrent, Download download) + { + var fileUrl = download.Link; + + if (String.IsNullOrWhiteSpace(fileUrl) || torrent.RdName == null) + { + return null; + } + + var uri = new Uri(fileUrl); + var torrentPath = RemoveInvalidPathChars(torrent.RdName); + + if (!Directory.Exists(torrentPath)) + { + Directory.CreateDirectory(torrentPath); + } + + var fileName = uri.Segments.Last(); + + fileName = HttpUtility.UrlDecode(fileName); + + fileName = FileHelper.RemoveInvalidFileNameChars(fileName); + + var filePath = Path.Combine(torrentPath, fileName); + + return filePath; + } + private static String RemoveInvalidPathChars(String path) { return String.Concat(path.Split(Path.GetInvalidPathChars())); diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index ddfd144..07e53f0 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -44,8 +44,9 @@ public class DownloadClient } var filePath = DownloadHelper.GetDownloadPath(_destinationPath, _torrent, _download); + var downloadPath = DownloadHelper.GetDownloadPath(_torrent, _download); - if (filePath == null) + if (filePath == null || downloadPath == null) { throw new Exception("Invalid download path"); } @@ -57,7 +58,7 @@ public class DownloadClient Downloader = Settings.Get.DownloadClient.Client switch { Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath), - Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(_download.RemoteId, _download.Link, filePath), + Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(_download.RemoteId, _download.Link, filePath, downloadPath), Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(_download.Link, filePath), _ => throw new Exception($"Unknown download client {Settings.Get.DownloadClient}") }; diff --git a/server/RdtClient.Service/Services/Downloaders/Aria2cDownloader.cs b/server/RdtClient.Service/Services/Downloaders/Aria2cDownloader.cs index 3acdc24..4f67c4b 100644 --- a/server/RdtClient.Service/Services/Downloaders/Aria2cDownloader.cs +++ b/server/RdtClient.Service/Services/Downloaders/Aria2cDownloader.cs @@ -15,16 +15,26 @@ public class Aria2cDownloader : IDownloader private readonly ILogger _logger; private readonly String _uri; private readonly String _filePath; + private readonly String _remotePath; private String? _gid; - public Aria2cDownloader(String? gid, String uri, String filePath) + public Aria2cDownloader(String? gid, String uri, String filePath, String downloadPath) { _logger = Log.ForContext(); _gid = gid; _uri = uri; _filePath = filePath; + if (!String.IsNullOrWhiteSpace(Settings.Get.DownloadClient.Aria2cDownloadPath)) + { + _remotePath = Path.Combine(Settings.Get.DownloadClient.Aria2cDownloadPath, downloadPath).Replace('\\', '/'); + } + else + { + _remotePath = _filePath; + } + var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(10) @@ -35,7 +45,7 @@ public class Aria2cDownloader : IDownloader public async Task Download() { - var path = Path.GetDirectoryName(_filePath); + var path = Path.GetDirectoryName(_remotePath); if (path == null) { @@ -44,7 +54,7 @@ public class Aria2cDownloader : IDownloader var fileName = Path.GetFileName(_filePath); - _logger.Debug($"Starting download of {_uri}, writing to path: {path}, fileName: {fileName}"); + _logger.Debug($"Starting download of {_uri}, writing to path: {_filePath} (on aria2: {_remotePath}), fileName: {fileName}"); if (String.IsNullOrWhiteSpace(_gid)) { @@ -82,7 +92,7 @@ public class Aria2cDownloader : IDownloader new Dictionary { { - "dir", path + "dir", path.Replace('\\', '/') }, { "out", fileName @@ -197,7 +207,7 @@ public class Aria2cDownloader : IDownloader { DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs { - Error = $"File not found at {_filePath}" + Error = $"File not found at {_filePath} (on aria2 {_remotePath})" }); break; }