diff --git a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs index f803c9d2f4..4548b500d7 100644 --- a/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs +++ b/src/Volo.Abp.AspNetCore.Mvc.UI/UI/Bundling/BundleManager.cs @@ -12,6 +12,8 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bundling.Styles; using Volo.Abp.AspNetCore.Mvc.UI.Theming; using Volo.Abp.DependencyInjection; using Volo.Abp.IO; +using Volo.Abp.VirtualFileSystem; +using Volo.Abp.VirtualFileSystem.Embedded; namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling { @@ -22,8 +24,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling private readonly IHostingEnvironment _hostingEnvironment; private readonly IScriptBundler _scriptBundler; private readonly IStyleBundler _styleBundler; - private readonly IThemeManager _themeManager; private readonly IServiceProvider _serviceProvider; + private readonly IDynamicFileProvider _dynamicFileProvider; private readonly ConcurrentDictionary _cache; @@ -32,13 +34,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling IScriptBundler scriptBundler, IStyleBundler styleBundler, IHostingEnvironment hostingEnvironment, - IThemeManager themeManager, - IServiceProvider serviceProvider) + IServiceProvider serviceProvider, IDynamicFileProvider dynamicFileProvider) { _hostingEnvironment = hostingEnvironment; _scriptBundler = scriptBundler; - _themeManager = themeManager; _serviceProvider = serviceProvider; + _dynamicFileProvider = dynamicFileProvider; _styleBundler = styleBundler; _options = options.Value; @@ -82,9 +83,19 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bundling protected virtual void SaveBundleResult(string bundleRelativePath, BundleResult bundleResult) { - var bundleFilePath = Path.Combine(_hostingEnvironment.WebRootPath, bundleRelativePath); - DirectoryHelper.CreateIfNotExists(Path.GetDirectoryName(bundleFilePath)); - File.WriteAllText(bundleFilePath, bundleResult.Content, Encoding.UTF8); + //TODO: Optimize? + var fileName = bundleRelativePath.Substring(bundleRelativePath.IndexOf('/') + 1); + + _dynamicFileProvider.AddOrUpdate( + new InMemoryFileInfo( + Encoding.UTF8.GetBytes(bundleResult.Content), + "/wwwroot/" + bundleRelativePath, //TODO: get rid of wwwroot! + fileName + ) + ); + //var bundleFilePath = Path.Combine(_hostingEnvironment.WebRootPath, bundleRelativePath); + //DirectoryHelper.CreateIfNotExists(Path.GetDirectoryName(bundleFilePath)); + //File.WriteAllText(bundleFilePath, bundleResult.Content, Encoding.UTF8); } public virtual void CreateStyleBundle(string bundleName, Action configureAction) diff --git a/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs index 6ab9b36a96..2cd14e0402 100644 --- a/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs +++ b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DictionaryBasedFileProvider.cs @@ -7,7 +7,7 @@ namespace Volo.Abp.VirtualFileSystem { public abstract class DictionaryBasedFileProvider : IFileProvider { - protected abstract Dictionary Files { get; } + protected abstract IDictionary Files { get; } public virtual IFileInfo GetFileInfo(string subpath) { @@ -16,7 +16,7 @@ namespace Volo.Abp.VirtualFileSystem return new NotFoundFileInfo(subpath); } - var file = Files.GetOrDefault(VirtualFilePathHelper.NormalizePath(subpath)); + var file = Files.GetOrDefault(NormalizePath(subpath)); if (file == null) { @@ -60,5 +60,10 @@ namespace Volo.Abp.VirtualFileSystem { return NullChangeToken.Singleton; } + + protected virtual string NormalizePath(string subpath) + { + return subpath; + } } } \ No newline at end of file diff --git a/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs new file mode 100644 index 0000000000..7bb625e94b --- /dev/null +++ b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/DynamicFileProvider.cs @@ -0,0 +1,31 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using Microsoft.Extensions.FileProviders; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.VirtualFileSystem +{ + //TODO: Implement Watch! + //TODO: Work with dictionaries? + public class DynamicFileProvider : DictionaryBasedFileProvider, IDynamicFileProvider, ISingletonDependency + { + protected override IDictionary Files => DynamicFiles; + + protected ConcurrentDictionary DynamicFiles { get; } + + public DynamicFileProvider() + { + DynamicFiles = new ConcurrentDictionary(); + } + + public void AddOrUpdate(IFileInfo fileInfo) + { + DynamicFiles.AddOrUpdate(fileInfo.PhysicalPath, fileInfo, (key, value) => fileInfo); + } + + public bool Delete(string filePath) + { + return DynamicFiles.TryRemove(filePath, out _); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs new file mode 100644 index 0000000000..d9ab30763a --- /dev/null +++ b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/InMemoryFileInfo.cs @@ -0,0 +1,36 @@ +using System; +using System.IO; +using Microsoft.Extensions.FileProviders; + +namespace Volo.Abp.VirtualFileSystem +{ + public class InMemoryFileInfo : IFileInfo + { + public bool Exists => true; + + public long Length => _fileContent.Length; + + public string PhysicalPath { get; } + + public string Name { get; } + + public DateTimeOffset LastModified { get; } + + public bool IsDirectory => false; + + private readonly byte[] _fileContent; + + public InMemoryFileInfo(byte[] fileContent, string physicalPath, string name) + { + PhysicalPath = physicalPath; + Name = name; + _fileContent = fileContent; + LastModified = DateTimeOffset.Now; + } + + public Stream CreateReadStream() + { + return new MemoryStream(_fileContent, false); + } + } +} diff --git a/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs index dd23a8c5e5..896d4a5ebc 100644 --- a/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs +++ b/src/Volo.Abp.VirtualFileSystem/Volo/Abp/VirtualFileSystem/VirtualFileProvider.cs @@ -10,53 +10,53 @@ namespace Volo.Abp.VirtualFileSystem { public class VirtualFileProvider : IVirtualFileProvider, ISingletonDependency { - private readonly IFileProvider _fileProvider; + private readonly IFileProvider _hybridFileProvider; private readonly VirtualFileSystemOptions _options; - public VirtualFileProvider(IOptions options) + public VirtualFileProvider(IOptions options, IDynamicFileProvider dynamicFileProvider) { _options = options.Value; - _fileProvider = CreateHybridProvider(); + _hybridFileProvider = CreateHybridProvider(dynamicFileProvider); } public virtual IFileInfo GetFileInfo(string subpath) { - return _fileProvider.GetFileInfo(subpath); + return _hybridFileProvider.GetFileInfo(subpath); } public virtual IDirectoryContents GetDirectoryContents(string subpath) { - return _fileProvider.GetDirectoryContents(subpath); + return _hybridFileProvider.GetDirectoryContents(subpath); } public virtual IChangeToken Watch(string filter) { - return _fileProvider.Watch(filter); + return _hybridFileProvider.Watch(filter); } - protected virtual IFileProvider CreateHybridProvider() + protected virtual IFileProvider CreateHybridProvider(IDynamicFileProvider dynamicFileProvider) { - IFileProvider fileProvider = new InternalVirtualFileProvider(_options); + var fileProviders = new List(); + + fileProviders.Add(dynamicFileProvider); if (_options.FileSets.PhysicalPaths.Any()) { - var fileProviders = _options.FileSets.PhysicalPaths - .Select(rootPath => new PhysicalFileProvider(rootPath)) - .Reverse() - .Cast() - .ToList(); - - fileProviders.Add(fileProvider); - - fileProvider = new CompositeFileProvider(fileProviders); + fileProviders.AddRange( + _options.FileSets.PhysicalPaths + .Select(rootPath => new PhysicalFileProvider(rootPath)) + .Reverse() + ); } - return fileProvider; + fileProviders.Add(new InternalVirtualFileProvider(_options)); + + return new CompositeFileProvider(fileProviders); } protected class InternalVirtualFileProvider : DictionaryBasedFileProvider { - protected override Dictionary Files => _files.Value; + protected override IDictionary Files => _files.Value; private readonly VirtualFileSystemOptions _options; private readonly Lazy> _files; @@ -81,6 +81,11 @@ namespace Volo.Abp.VirtualFileSystem return files; } + + protected override string NormalizePath(string subpath) + { + return VirtualFilePathHelper.NormalizePath(subpath); + } } } } \ No newline at end of file