-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add cache busting parameter to media thumbnails and links in Media Library (Lombiq Technologies: OCORE-143) #15276
Changes from 7 commits
f440378
6a3b8d3
6f9525b
5e9bd19
1399c16
8e75215
1ec9926
bbee61a
ec4ef25
04aca54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -6,7 +6,9 @@ | |||||||
using Microsoft.AspNetCore.Authorization; | ||||||||
using Microsoft.AspNetCore.Http; | ||||||||
using Microsoft.AspNetCore.Mvc; | ||||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures; | ||||||||
using Microsoft.AspNetCore.StaticFiles; | ||||||||
using Microsoft.Extensions.DependencyInjection; | ||||||||
using Microsoft.Extensions.Localization; | ||||||||
using Microsoft.Extensions.Logging; | ||||||||
using Microsoft.Extensions.Options; | ||||||||
|
@@ -30,6 +32,8 @@ public class AdminController : Controller | |||||||
private readonly MediaOptions _mediaOptions; | ||||||||
private readonly IUserAssetFolderNameProvider _userAssetFolderNameProvider; | ||||||||
private readonly IChunkFileUploadService _chunkFileUploadService; | ||||||||
private readonly IFileVersionProvider _fileVersionProvider; | ||||||||
private readonly IServiceProvider _serviceProvider; | ||||||||
|
||||||||
public AdminController( | ||||||||
IMediaFileStore mediaFileStore, | ||||||||
|
@@ -40,8 +44,9 @@ public AdminController( | |||||||
ILogger<AdminController> logger, | ||||||||
IStringLocalizer<AdminController> stringLocalizer, | ||||||||
IUserAssetFolderNameProvider userAssetFolderNameProvider, | ||||||||
IChunkFileUploadService chunkFileUploadService | ||||||||
) | ||||||||
IChunkFileUploadService chunkFileUploadService, | ||||||||
IFileVersionProvider fileVersionProvider, | ||||||||
IServiceProvider serviceProvider) | ||||||||
MikeAlhayek marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
{ | ||||||||
_mediaFileStore = mediaFileStore; | ||||||||
_mediaNameNormalizerService = mediaNameNormalizerService; | ||||||||
|
@@ -52,6 +57,8 @@ IChunkFileUploadService chunkFileUploadService | |||||||
S = stringLocalizer; | ||||||||
_userAssetFolderNameProvider = userAssetFolderNameProvider; | ||||||||
_chunkFileUploadService = chunkFileUploadService; | ||||||||
_fileVersionProvider = fileVersionProvider; | ||||||||
_serviceProvider = serviceProvider; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
} | ||||||||
|
||||||||
public async Task<IActionResult> Index() | ||||||||
|
@@ -115,7 +122,10 @@ public async Task<ActionResult<IEnumerable<object>>> GetMediaItems(string path, | |||||||
var allowedExtensions = GetRequestedExtensions(extensions, false); | ||||||||
|
||||||||
var allowed = _mediaFileStore.GetDirectoryContentAsync(path) | ||||||||
.WhereAwait(async e => !e.IsDirectory && (allowedExtensions.Count == 0 || allowedExtensions.Contains(Path.GetExtension(e.Path))) && await _authorizationService.AuthorizeAsync(User, Permissions.ManageMediaFolder, (object)e.Path)) | ||||||||
.WhereAwait(async e => | ||||||||
!e.IsDirectory && | ||||||||
(allowedExtensions.Count == 0 || allowedExtensions.Contains(Path.GetExtension(e.Path))) && | ||||||||
MikeAlhayek marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
await _authorizationService.AuthorizeAsync(User, Permissions.ManageMediaFolder, (object)e.Path)) | ||||||||
.Select(e => CreateFileResult(e)); | ||||||||
|
||||||||
return Ok(await allowed.ToListAsync()); | ||||||||
|
@@ -202,6 +212,9 @@ public async Task<IActionResult> Upload(string path, string extensions) | |||||||
|
||||||||
var mediaFile = await _mediaFileStore.GetFileInfoAsync(mediaFilePath); | ||||||||
|
||||||||
stream.Position = 0; | ||||||||
await PreCacheRemoteMedia(mediaFile, stream); | ||||||||
|
||||||||
result.Add(CreateFileResult(mediaFile)); | ||||||||
} | ||||||||
catch (Exception ex) | ||||||||
|
@@ -309,7 +322,10 @@ public async Task<IActionResult> MoveMedia(string oldPath, string newPath) | |||||||
|
||||||||
await _mediaFileStore.MoveFileAsync(oldPath, newPath); | ||||||||
|
||||||||
return Ok(); | ||||||||
var newFileInfo = await _mediaFileStore.GetFileInfoAsync(newPath); | ||||||||
await PreCacheRemoteMedia(newFileInfo); | ||||||||
|
||||||||
return Ok(new { newUrl = GetCacheBustingMediaPublicUrl(newPath) }); | ||||||||
} | ||||||||
|
||||||||
[HttpPost] | ||||||||
|
@@ -442,7 +458,7 @@ public object CreateFileResult(IFileStoreEntry mediaFile) | |||||||
size = mediaFile.Length, | ||||||||
lastModify = mediaFile.LastModifiedUtc.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds, | ||||||||
folder = mediaFile.DirectoryPath, | ||||||||
url = _mediaFileStore.MapPathToPublicUrl(mediaFile.Path), | ||||||||
url = GetCacheBustingMediaPublicUrl(mediaFile.Path), | ||||||||
mediaPath = mediaFile.Path, | ||||||||
mime = contentType ?? "application/octet-stream", | ||||||||
mediaText = string.Empty, | ||||||||
|
@@ -490,5 +506,38 @@ private HashSet<string> GetRequestedExtensions(string exts, bool fallback) | |||||||
|
||||||||
return []; | ||||||||
} | ||||||||
|
||||||||
private string GetCacheBustingMediaPublicUrl(string path) => | ||||||||
Piedone marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
_fileVersionProvider.AddFileVersionToPath(HttpContext.Request.PathBase, _mediaFileStore.MapPathToPublicUrl(path)); | ||||||||
|
||||||||
// If a remote storage is used, then we need to preemptively cache the newly uploaded or renamed file. Without | ||||||||
// this, the Media Library page will try to load the thumbnail without a cache busting parameter, since | ||||||||
// ShellFileVersionProvider won't find it in the local cache. | ||||||||
// This is not required for files moved across folders, because the folder will be reopened anyway. | ||||||||
private async Task PreCacheRemoteMedia(IFileStoreEntry mediaFile, Stream stream = null) | ||||||||
{ | ||||||||
var mediaFileStoreCache = _serviceProvider.GetService<IMediaFileStoreCache>(); | ||||||||
if (mediaFileStoreCache == null) | ||||||||
Comment on lines
+522
to
+523
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
{ | ||||||||
return; | ||||||||
} | ||||||||
|
||||||||
Stream localStream = null; | ||||||||
MikeAlhayek marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
|
||||||||
if (stream == null) | ||||||||
{ | ||||||||
localStream = await _mediaFileStore.GetFileStreamAsync(mediaFile); | ||||||||
stream = localStream; | ||||||||
Piedone marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
} | ||||||||
|
||||||||
try | ||||||||
{ | ||||||||
await mediaFileStoreCache.SetCacheAsync(stream, mediaFile, HttpContext.RequestAborted); | ||||||||
} | ||||||||
finally | ||||||||
{ | ||||||||
localStream?.Dispose(); | ||||||||
} | ||||||||
} | ||||||||
} | ||||||||
} |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.