diff --git a/src/OrchardCore.Cms.Web/appsettings.json b/src/OrchardCore.Cms.Web/appsettings.json index d01510ee0f9..cc814fe6dc2 100644 --- a/src/OrchardCore.Cms.Web/appsettings.json +++ b/src/OrchardCore.Cms.Web/appsettings.json @@ -58,7 +58,8 @@ // "AllowedFileExtensions": [".jpg",".jpeg",".png",".gif",".ico",".svg",".webp",".pdf",".doc",".docx",".ppt",".pptx",".pps",".ppsx",".odt",".xls",".xlsx",".psd",".mp3",".m4a",".ogg",".wav",".mp4",".m4v",".mov",".wmv",".avi",".mpg",".ogv",".3gp",".webm"], // "ContentSecurityPolicy": "default-src 'self'; style-src 'unsafe-inline'", // "MaxUploadChunkSize": 104857600, - // "TemporaryFileLifetime": "01:00:00" + // "TemporaryFileLifetime": "01:00:00", + // "OverwriteMedia": false //}, // See https://docs.orchardcore.net/en/latest/reference/modules/Media.AmazonS3/#configuration to configure media storage in Amazon S3 Storage. //"OrchardCore_Media_AmazonS3": { diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/RemotePublishing/MetaWeblogHandler.cs b/src/OrchardCore.Modules/OrchardCore.Lists/RemotePublishing/MetaWeblogHandler.cs index 51c4a22ce94..c2dc08a7de7 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/RemotePublishing/MetaWeblogHandler.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/RemotePublishing/MetaWeblogHandler.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Metadata; using OrchardCore.ContentManagement.Metadata.Models; @@ -32,6 +33,8 @@ public class MetaWeblogHandler : IXmlRpcHandler private readonly IMembershipService _membershipService; private readonly IEnumerable _metaWeblogDrivers; private readonly ISession _session; + private readonly MediaOptions _mediaOptions; + protected readonly IStringLocalizer S; public MetaWeblogHandler( @@ -42,6 +45,7 @@ public MetaWeblogHandler( IContentDefinitionManager contentDefinitionManager, IMediaFileStore mediaFileStore, IEnumerable metaWeblogDrivers, + IOptions mediaOptions, IStringLocalizer localizer) { _contentManager = contentManager; @@ -51,6 +55,7 @@ public MetaWeblogHandler( _session = session; _mediaFileStore = mediaFileStore; _membershipService = membershipService; + _mediaOptions = mediaOptions.Value; S = localizer; } @@ -157,7 +162,7 @@ private async Task MetaWeblogNewMediaObjectAsync(string userName, st try { stream = new MemoryStream(bits); - filePath = await _mediaFileStore.CreateFileFromStreamAsync(filePath, stream); + filePath = await _mediaFileStore.CreateFileFromStreamAsync(filePath, stream, _mediaOptions.OverwriteMedia); } finally { diff --git a/src/OrchardCore.Modules/OrchardCore.Media/Controllers/AdminController.cs b/src/OrchardCore.Modules/OrchardCore.Media/Controllers/AdminController.cs index e76f1623080..817630371a7 100644 --- a/src/OrchardCore.Modules/OrchardCore.Media/Controllers/AdminController.cs +++ b/src/OrchardCore.Modules/OrchardCore.Media/Controllers/AdminController.cs @@ -226,7 +226,7 @@ public async Task Upload(string path, string extensions) { var mediaFilePath = _mediaFileStore.Combine(path, fileName); stream = file.OpenReadStream(); - mediaFilePath = await _mediaFileStore.CreateFileFromStreamAsync(mediaFilePath, stream); + mediaFilePath = await _mediaFileStore.CreateFileFromStreamAsync(mediaFilePath, stream, _mediaOptions.OverwriteMedia); var mediaFile = await _mediaFileStore.GetFileInfoAsync(mediaFilePath); diff --git a/src/OrchardCore.Modules/OrchardCore.Media/Services/MediaOptionsConfiguration.cs b/src/OrchardCore.Modules/OrchardCore.Media/Services/MediaOptionsConfiguration.cs index b7a415705e6..ae312fe24e4 100644 --- a/src/OrchardCore.Modules/OrchardCore.Media/Services/MediaOptionsConfiguration.cs +++ b/src/OrchardCore.Modules/OrchardCore.Media/Services/MediaOptionsConfiguration.cs @@ -102,6 +102,7 @@ public void Configure(MediaOptions options) options.UseTokenizedQueryString = section.GetValue("UseTokenizedQueryString", DefaultUseTokenizedQueryString); options.MaxUploadChunkSize = section.GetValue(nameof(options.MaxUploadChunkSize), DefaultMaxUploadChunkSize); options.TemporaryFileLifetime = section.GetValue(nameof(options.TemporaryFileLifetime), _defaultTemporaryFileLifeTime); + options.OverwriteMedia = section.GetValue("OverwriteMedia", false); var contentSecurityPolicy = section.GetValue("ContentSecurityPolicy", DefaultContentSecurityPolicy); diff --git a/src/OrchardCore/OrchardCore.Media.Abstractions/MediaOptions.cs b/src/OrchardCore/OrchardCore.Media.Abstractions/MediaOptions.cs index 53aca54f7eb..068025c415f 100644 --- a/src/OrchardCore/OrchardCore.Media.Abstractions/MediaOptions.cs +++ b/src/OrchardCore/OrchardCore.Media.Abstractions/MediaOptions.cs @@ -5,6 +5,8 @@ namespace OrchardCore.Media; public class MediaOptions { + public const string EncryptedCommandCacheKeyPrefix = "MediaCommands:"; + /// /// The accepted sizes for custom width and height. /// When is enabled all sizes are valid @@ -94,5 +96,8 @@ public class MediaOptions /// public TimeSpan TemporaryFileLifetime { get; set; } - public const string EncryptedCommandCacheKeyPrefix = "MediaCommands:"; + /// + /// Gets or sets whether media files should be overwritten when uploading a file with the same name. Defaults to . + /// + public bool OverwriteMedia { get; set; } } diff --git a/src/OrchardCore/OrchardCore.Shells.Azure/Extensions/BlobShellsOrchardCoreBuilderExtensions.cs b/src/OrchardCore/OrchardCore.Shells.Azure/Extensions/BlobShellsOrchardCoreBuilderExtensions.cs index eb5d280ec83..7e155f63983 100644 --- a/src/OrchardCore/OrchardCore.Shells.Azure/Extensions/BlobShellsOrchardCoreBuilderExtensions.cs +++ b/src/OrchardCore/OrchardCore.Shells.Azure/Extensions/BlobShellsOrchardCoreBuilderExtensions.cs @@ -6,6 +6,7 @@ using OrchardCore.Environment.Shell; using OrchardCore.Environment.Shell.Configuration; using OrchardCore.FileStorage.AzureBlob; +using OrchardCore.Media; using OrchardCore.Modules; using OrchardCore.Shells.Azure.Configuration; using OrchardCore.Shells.Azure.Services; @@ -33,10 +34,11 @@ public static OrchardCoreBuilder AddAzureShellsConfiguration(this OrchardCoreBui var clock = sp.GetRequiredService(); var contentTypeProvider = sp.GetRequiredService(); + var mediaOptions = sp.GetService>().Value; var fileStore = new BlobFileStore(blobOptions, clock, contentTypeProvider); - return new BlobShellsFileStore(fileStore); + return new BlobShellsFileStore(fileStore, mediaOptions); }); services.Replace(ServiceDescriptor.Singleton(sp => diff --git a/src/OrchardCore/OrchardCore.Shells.Azure/OrchardCore.Shells.Azure.csproj b/src/OrchardCore/OrchardCore.Shells.Azure/OrchardCore.Shells.Azure.csproj index 502575cccc1..cf60697a1c9 100644 --- a/src/OrchardCore/OrchardCore.Shells.Azure/OrchardCore.Shells.Azure.csproj +++ b/src/OrchardCore/OrchardCore.Shells.Azure/OrchardCore.Shells.Azure.csproj @@ -16,6 +16,7 @@ + diff --git a/src/OrchardCore/OrchardCore.Shells.Azure/Services/BlobShellsFileStore.cs b/src/OrchardCore/OrchardCore.Shells.Azure/Services/BlobShellsFileStore.cs index caf56fb551e..a5add99b6b3 100644 --- a/src/OrchardCore/OrchardCore.Shells.Azure/Services/BlobShellsFileStore.cs +++ b/src/OrchardCore/OrchardCore.Shells.Azure/Services/BlobShellsFileStore.cs @@ -1,18 +1,21 @@ using OrchardCore.FileStorage; +using OrchardCore.Media; namespace OrchardCore.Shells.Azure.Services; public class BlobShellsFileStore : IShellsFileStore { private readonly IFileStore _fileStore; + private readonly MediaOptions _mediaOptions; - public BlobShellsFileStore(IFileStore fileStore) + public BlobShellsFileStore(IFileStore fileStore, MediaOptions mediaOptions) { _fileStore = fileStore; + _mediaOptions = mediaOptions; } public Task CreateFileFromStreamAsync(string path, Stream inputStream) - => _fileStore.CreateFileFromStreamAsync(path, inputStream, true); + => _fileStore.CreateFileFromStreamAsync(path, inputStream, _mediaOptions.OverwriteMedia); public Task GetFileInfoAsync(string path) => _fileStore.GetFileInfoAsync(path); diff --git a/src/docs/releases/3.0.0.md b/src/docs/releases/3.0.0.md index 90b7c91e0b3..6d665ccf478 100644 --- a/src/docs/releases/3.0.0.md +++ b/src/docs/releases/3.0.0.md @@ -102,6 +102,11 @@ will return `false` for administrators, even though they still have full access. {% assign isAuthorized = User | has_permission: "AccessAdminPanel" %} ``` +### Media Module + +An `OverwriteMedia` option has been added to `MediaOptions` to allow you to configure whether the media will be overwritten if it exists or not. + + ### Sealing Types Many type commonly used by classes can be `sealed`, which improves runtime performance. While it's not mandatory, we recommend that you consider applying this improvement to your own extensions as well. We've implemented this enhancement in pull request [#16897](https://github.com/OrchardCMS/OrchardCore/pull/16897).