From 9829e02a38344a495f85434c9f283a776bd3cdb9 Mon Sep 17 00:00:00 2001 From: REDCODE Date: Wed, 8 Jul 2026 03:27:18 +0200 Subject: [PATCH] fix: download button now fetches blob and triggers actual file download Previously the download link just navigated cross-origin to the media URL. Now uses JS interop to fetch the file as a blob, create an object URL, and trigger a browser download via a hidden anchor element. --- MilkStream.Client/Components/Pages/Home.razor | 10 +++++++--- MilkStream.Client/Components/Pages/Home.razor.css | 3 +++ MilkStream.Client/wwwroot/js/masonryObserver.js | 13 +++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/MilkStream.Client/Components/Pages/Home.razor b/MilkStream.Client/Components/Pages/Home.razor index b8fc0e7..ad05632 100644 --- a/MilkStream.Client/Components/Pages/Home.razor +++ b/MilkStream.Client/Components/Pages/Home.razor @@ -101,10 +101,10 @@ title="View full size" @onclick:stopPropagation="true"> - + @@ -217,6 +217,10 @@ } } + async Task DownloadOriginal(Guid id) { + await jsRuntime.InvokeVoidAsync("masonryObserver.downloadFile", OriginalUrl(id)); + } + static string GetAspectRatio(AssetPreviewDto asset) { if (asset.ResolutionWidth > 0 && asset.ResolutionHeight > 0) return $"{asset.ResolutionWidth} / {asset.ResolutionHeight}"; diff --git a/MilkStream.Client/Components/Pages/Home.razor.css b/MilkStream.Client/Components/Pages/Home.razor.css index 3e4da11..ade1ee7 100644 --- a/MilkStream.Client/Components/Pages/Home.razor.css +++ b/MilkStream.Client/Components/Pages/Home.razor.css @@ -204,6 +204,9 @@ transition: color 0.15s; display: flex; align-items: center; + background: none; + border: none; + cursor: pointer; } .preview-action-btn:hover { diff --git a/MilkStream.Client/wwwroot/js/masonryObserver.js b/MilkStream.Client/wwwroot/js/masonryObserver.js index eb5790a..117800c 100644 --- a/MilkStream.Client/wwwroot/js/masonryObserver.js +++ b/MilkStream.Client/wwwroot/js/masonryObserver.js @@ -30,5 +30,18 @@ window.masonryObserver = { unlockBodyScroll: function () { document.body.style.overflow = ''; + }, + + downloadFile: async function (url) { + const response = await fetch(url); + const blob = await response.blob(); + const blobUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = blobUrl; + a.download = ''; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(blobUrl); } };