C# .NET8.0 webapi动态托管任意文件夹静态资源

1、默认

默认情况下,在webapi项目中使用 UseStaticFiles 或者 UseFileServer即可顺便托管wwwroot静态资源,也可以设置defaultFileProvider选项定位到自定义文件夹,比如

FileServerOptions options = new FileServerOptions
{
    FileProvider = PhysicalFileProvider("自定义根目录"),
    EnableDefaultFiles = true,
    EnableDirectoryBrowsing = false,
};
app.UseFileServer(options);

2、动态多目录

通过实现IFileProvider接口,包一层,实现根据域名或者path选择不同的PhysicalFileProvider来访问不同的根目录

配置

builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton<DynamicFileProvider>();

IHttpContextAccessor httpContextAccessor = app.Services.GetService<IHttpContextAccessor >()
DynamicFileProvider dfp = app.Services.GetService<DynamicFileProvider>();
//设置一个默认目录
dfp.SetDefault(Path.Combine(app.Environment.ContentRootPath, "web"));
FileServerOptions options = new FileServerOptions
{
    FileProvider = dfp,
    EnableDefaultFiles = true,
    EnableDirectoryBrowsing = false,
};
app.UseFileServer(options);

实现接口

public class DynamicFileProvider : IFileProvider
{

    private PhysicalFileProvider defaultFileProvider;
    private readonly IHttpContextAccessor httpContextAccessor;
    public DynamicFileProvider(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
        SearchTask();
    }

    public void SetDefault(string defaultPath)
    {
        if (Directory.Exists(defaultPath) == false)
        {
            Directory.CreateDirectory(defaultPath);
        }
        this.defaultFileProvider = new PhysicalFileProvider(defaultPath);
    }

    public IFileInfo GetFileInfo(string subpath)
    {
        IFileProvider fileProvider = GetFileProvider();
        return fileProvider.GetFileInfo(subpath);
    }
    public IDirectoryContents GetDirectoryContents(string subpath)
    {
        IFileProvider fileProvider = GetFileProvider();
        return fileProvider.GetDirectoryContents(subpath);
    }
    public IChangeToken Watch(string filter)
    {
        IFileProvider fileProvider = GetFileProvider();
        return fileProvider.Watch(filter);
    }

    private IFileProvider GetFileProvider()
    {
        HttpContext httpContext = httpContextAccessor.HttpContext;
        string host = httpContext?.Request.Host.Host ?? string.Empty;
        string path = httpContext?.Request.Path ?? string.Empty;

        FileProviderInfo provider;
        if (IPAddress.TryParse(host, out _) == false)
        {
            //根据 host.Split('.')[0] 获取
        }
        if (string.IsNullOrWhiteSpace(path) == false) 
        {
            //根据 path.Split('/')[1] 获取
        }
        //都没有就默认的
        return defaultFileProvider;
    }
}