From ac47edc52df197e98da9855a68649cb7d6061a07 Mon Sep 17 00:00:00 2001 From: Kieran Date: Wed, 2 Mar 2022 19:19:02 +0000 Subject: [PATCH] Serve files directly from cloud storage --- VoidCat/Controllers/DownloadController.cs | 11 +++++----- VoidCat/Model/VoidFile.cs | 2 +- VoidCat/Model/VoidFileMeta.cs | 5 +++++ VoidCat/Model/VoidSettings.cs | 1 + VoidCat/Services/Files/S3FileMetadataStore.cs | 22 ++++++++++++++----- VoidCat/Services/Files/S3FileStore.cs | 1 - VoidCat/spa/src/FilePreview.js | 5 +++-- 7 files changed, 32 insertions(+), 15 deletions(-) diff --git a/VoidCat/Controllers/DownloadController.cs b/VoidCat/Controllers/DownloadController.cs index 9fdabd2..5391154 100644 --- a/VoidCat/Controllers/DownloadController.cs +++ b/VoidCat/Controllers/DownloadController.cs @@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Mvc; using VoidCat.Model; using VoidCat.Model.Paywall; using VoidCat.Services.Abstractions; -using VoidCat.Services.Files; namespace VoidCat.Controllers; @@ -41,7 +40,7 @@ public class DownloadController : Controller var voidFile = await SetupDownload(gid); if (voidFile == default) return; - var egressReq = new EgressRequest(gid, GetRanges(Request, (long) voidFile!.Metadata!.Size)); + var egressReq = new EgressRequest(gid, GetRanges(Request, (long)voidFile!.Metadata!.Size)); if (egressReq.Ranges.Count() > 1) { _logger.LogWarning("Multi-range request not supported!"); @@ -53,10 +52,10 @@ public class DownloadController : Controller } else if (egressReq.Ranges.Count() == 1) { - Response.StatusCode = (int) HttpStatusCode.PartialContent; + Response.StatusCode = (int)HttpStatusCode.PartialContent; if (egressReq.Ranges.Sum(a => a.Size) == 0) { - Response.StatusCode = (int) HttpStatusCode.RequestedRangeNotSatisfiable; + Response.StatusCode = (int)HttpStatusCode.RequestedRangeNotSatisfiable; return; } } @@ -92,7 +91,7 @@ public class DownloadController : Controller var orderId = Request.Headers.GetHeader("V-OrderId") ?? Request.Query["orderId"]; if (!await IsOrderPaid(orderId)) { - Response.StatusCode = (int) HttpStatusCode.PaymentRequired; + Response.StatusCode = (int)HttpStatusCode.PaymentRequired; return default; } } @@ -133,4 +132,4 @@ public class DownloadController : Controller } } } -} \ No newline at end of file +} diff --git a/VoidCat/Model/VoidFile.cs b/VoidCat/Model/VoidFile.cs index 4cecef0..c62729c 100644 --- a/VoidCat/Model/VoidFile.cs +++ b/VoidCat/Model/VoidFile.cs @@ -10,7 +10,7 @@ namespace VoidCat.Model /// [JsonConverter(typeof(Base58GuidConverter))] public Guid Id { get; init; } - + /// /// Metadta related to the file /// diff --git a/VoidCat/Model/VoidFileMeta.cs b/VoidCat/Model/VoidFileMeta.cs index 2abb479..aaece05 100644 --- a/VoidCat/Model/VoidFileMeta.cs +++ b/VoidCat/Model/VoidFileMeta.cs @@ -53,6 +53,11 @@ public record VoidFileMeta : IVoidFileMeta /// public string? Digest { get; init; } + /// + /// Url to download the file + /// + public Uri? Url { get; set; } + /// /// User who uploaded the file /// diff --git a/VoidCat/Model/VoidSettings.cs b/VoidCat/Model/VoidSettings.cs index 570be89..7a40e48 100644 --- a/VoidCat/Model/VoidSettings.cs +++ b/VoidCat/Model/VoidSettings.cs @@ -34,6 +34,7 @@ namespace VoidCat.Model public sealed record CloudStorageSettings { + public bool ServeFromCloud { get; init; } public S3BlobConfig? S3 { get; set; } } diff --git a/VoidCat/Services/Files/S3FileMetadataStore.cs b/VoidCat/Services/Files/S3FileMetadataStore.cs index 4fd1c7d..91a0824 100644 --- a/VoidCat/Services/Files/S3FileMetadataStore.cs +++ b/VoidCat/Services/Files/S3FileMetadataStore.cs @@ -5,20 +5,21 @@ using VoidCat.Services.Abstractions; namespace VoidCat.Services.Files; -// ReSharper disable once InconsistentNaming public class S3FileMetadataStore : IFileMetadataStore { private readonly ILogger _logger; private readonly AmazonS3Client _client; private readonly S3BlobConfig _config; - + private readonly bool _includeUrl; + public S3FileMetadataStore(VoidSettings settings, ILogger logger) { _logger = logger; + _includeUrl = settings.CloudStorage?.ServeFromCloud ?? false; _config = settings.CloudStorage!.S3!; _client = _config.CreateClient(); } - + public async ValueTask Get(Guid id) where TMeta : VoidFileMeta { try @@ -27,7 +28,18 @@ public class S3FileMetadataStore : IFileMetadataStore using var sr = new StreamReader(obj.ResponseStream); var json = await sr.ReadToEndAsync(); - return JsonConvert.DeserializeObject(json); + var ret = JsonConvert.DeserializeObject(json); + if (ret != default && _includeUrl) + { + var ub = new UriBuilder(_config.ServiceUrl!) + { + Path = $"/{_config.BucketName}/{id}" + }; + + ret.Url = ub.Uri; + } + + return ret; } catch (AmazonS3Exception aex) { @@ -54,4 +66,4 @@ public class S3FileMetadataStore : IFileMetadataStore } private static string ToKey(Guid id) => $"{id}-metadata"; -} \ No newline at end of file +} diff --git a/VoidCat/Services/Files/S3FileStore.cs b/VoidCat/Services/Files/S3FileStore.cs index 318aac1..ae67b28 100644 --- a/VoidCat/Services/Files/S3FileStore.cs +++ b/VoidCat/Services/Files/S3FileStore.cs @@ -5,7 +5,6 @@ using VoidCat.Services.Abstractions; namespace VoidCat.Services.Files; -// ReSharper disable once InconsistentNaming public class S3FileStore : StreamFileStore, IFileStore { private readonly IFileInfoManager _fileInfo; diff --git a/VoidCat/spa/src/FilePreview.js b/VoidCat/spa/src/FilePreview.js index 8ab39ba..ab0a88e 100644 --- a/VoidCat/spa/src/FilePreview.js +++ b/VoidCat/spa/src/FilePreview.js @@ -114,13 +114,14 @@ export function FilePreview() { useEffect(() => { if (info) { + let fileLink = info.metadata?.url ?? `${ApiHost}/d/${info.id}`; let order = window.localStorage.getItem(`paywall-${info.id}`); if (order) { let orderObj = JSON.parse(order); setOrder(orderObj); - setLink(`${ApiHost}/d/${info.id}?orderId=${orderObj.id}`); + setLink(`${fileLink}?orderId=${orderObj.id}`); } else { - setLink(`${ApiHost}/d/${info.id}`); + setLink(fileLink); } } }, [info]);