虚拟文件系统
虚拟文件系统能够管理在文件系统(磁盘)上物理不存在的文件。它主要用于将(js、css、图像等)文件嵌入程序集,并在运行时像物理文件一样使用它们。
安装
大多数情况下您无需手动安装此包,因为它已预先安装在 应用程序启动模板中。
Volo.Abp.VirtualFileSystem是虚拟文件系统的主包。
使用ABP CLI将此包添加到您的项目:
- 如未安装,请先安装 ABP CLI
- 在要添加
Volo.Abp.VirtualFileSystem包的.csproj文件目录下打开命令行(终端) - 运行
abp add-package Volo.Abp.VirtualFileSystem命令
如需手动安装,请为项目安装 Volo.Abp.VirtualFileSystem NuGet包,并在项目的 ABP模块 类中添加 [DependsOn(typeof(AbpVirtualFileSystemModule))]
使用嵌入式文件
嵌入文件
文件需先标记为嵌入式资源才能嵌入程序集。最简单方法是在解决方案资源管理器中选择文件,然后在属性窗口中将生成操作设置为嵌入式资源。示例:
如需添加多个文件,此方法可能繁琐。您也可以直接编辑.csproj文件:
<ItemGroup>
<EmbeddedResource Include="MyResources\**\*.*" />
<Content Remove="MyResources\**\*.*" />
</ItemGroup>
此配置会递归添加项目MyResources文件夹下的所有文件(包括将来添加的文件)。
如果文件名包含特殊字符,嵌入项目/程序集可能导致问题。为解决此限制:
- 向包含嵌入式资源的项目添加Microsoft.Extensions.FileProviders.Embedded NuGet包
- 在
.csproj文件的<PropertyGroup>...</PropertyGroup>部分添加<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
虽然这两个步骤是可选的且ABP无需这些配置也能工作,但强烈建议进行配置
配置AbpVirtualFileSystemOptions
在模块的ConfigureServices方法中使用AbpVirtualFileSystemOptions选项类向虚拟文件系统注册嵌入式文件。
示例:向虚拟文件系统添加嵌入式文件
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<MyModule>();
});
AddEmbedded扩展方法接收一个类,从给定类的程序集中查找所有嵌入式文件并将其注册到虚拟文件系统。
AddEmbedded可接受两个可选参数:
baseNamespace:仅当未配置上述GenerateEmbeddedFilesManifest步骤且根命名空间非空时需要。此时请在此处设置根命名空间baseFolder:如果不希望暴露项目中所有嵌入式文件,仅想暴露特定文件夹(及子文件夹/文件),可设置相对于项目根文件夹的基础文件夹
示例:添加项目中MyResources文件夹下的文件
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<MyModule>(
baseNamespace: "Acme.BookStore",
baseFolder: "/MyResources"
);
});
此示例假设:
- 项目根(默认)命名空间为
Acme.BookStore - 项目有名为
MyResources的文件夹 - 仅想将
MyResources文件夹添加到虚拟文件系统
IVirtualFileProvider
将文件嵌入程序集并注册到虚拟文件系统后,可使用IVirtualFileProvider接口获取文件或目录内容:
public class MyService : ITransientDependency
{
private readonly IVirtualFileProvider _virtualFileProvider;
public MyService(IVirtualFileProvider virtualFileProvider)
{
_virtualFileProvider = virtualFileProvider;
}
public void Test()
{
//获取单个文件
var file = _virtualFileProvider
.GetFileInfo("/MyResources/js/test.js");
var fileContent = file.ReadAsString();
//获取目录下所有文件/目录
var directoryContents = _virtualFileProvider
.GetDirectoryContents("/MyResources/js");
}
}
ASP.NET Core集成
虚拟文件系统与ASP.NET深度集成:
- 虚拟文件可像Web应用中的物理(静态)文件一样使用
- Js、css、图像文件及所有其他Web内容类型可嵌入程序集并像物理文件一样使用
- 应用程序(或其他模块)可覆盖模块的虚拟文件,就像将同名同扩展名文件放入虚拟文件的相同文件夹
静态虚拟文件文件夹
默认情况下,ASP.NET Core仅允许wwwroot文件夹包含客户端使用的静态文件。使用虚拟文件系统时,以下文件夹也可包含静态文件:
- Pages
- Views
- Components
- Themes
这允许在.cshtml文件附近添加.js、.css等文件,更便于开发和维护项目
开发期间处理嵌入式文件
将文件嵌入程序集并通过引用程序集(或添加NuGet包)从另一个项目使用,对于创建可重用模块非常宝贵。但这使得模块本身的开发稍显困难。
假设您正在开发包含嵌入式JavaScript文件的模块。每次更改此文件时都必须重新编译项目、重启应用程序并刷新浏览器页面才能生效。显然这非常耗时且繁琐。
需要的是应用程序在开发时直接使用物理文件,浏览器刷新即可反映JavaScript文件中的任何更改。ReplaceEmbeddedByPhysical方法实现了这一切。
以下示例显示了一个依赖于包含嵌入式文件的模块(MyModule)的应用程序。该应用程序在开发时可访问模块的源代码。
[DependsOn(typeof(MyModule))]
public class MyWebAppModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
if (hostingEnvironment.IsDevelopment()) //仅开发时使用
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<MyModule>(
Path.Combine(
hostingEnvironment.ContentRootPath,
string.Format(
"..{0}MyModuleProject",
Path.DirectorySeparatorChar
)
)
);
});
}
}
}
以上代码假设MyWebAppModule和MyModule是Visual Studio解决方案中的两个不同项目,且MyWebAppModule依赖于MyModule。
应用程序启动模板 已对本地化文件使用此技术。因此当更改本地化文件时会自动检测变更
替换/覆盖虚拟文件
虚拟文件系统在运行时创建统一文件系统,其中实际文件在开发时分布在不同模块中。
如果两个模块向同一虚拟路径(如my-path/my-file.css)添加文件,后添加的文件将覆盖前一个文件(模块依赖顺序决定文件添加顺序)。
此功能允许应用程序覆盖/替换所用模块定义的任何虚拟文件。这是ABP的基本可扩展特性之一。
因此如需替换模块文件,只需在模块/应用程序中创建完全相同的路径文件
物理文件
物理文件总是覆盖虚拟文件。这意味着如果在/wwwroot/my-folder/my-file.css放置文件,它将覆盖虚拟文件系统中相同位置的文件。因此需要了解模块中定义的文件路径才能覆盖它们
抠丁客



