根据请求上下文动态设置静态文件存储目录

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了根据请求上下文动态设置静态文件存储目录相关的知识,希望对你有一定的参考价值。

前言

上次,我们实现了根据 subpath 特定格式《动态设置静态文件存储目录》。

例如:

subpath静态文件路径
/userAId/1.jpgc:\\abc\\userAId\\1.jpg
/userBId/1.jpgd:\\xyz\\123\\userBId\\1.jpg

但是,如果 subpath 不能有这种特定格式,只能用通用格式,比如https://<hostname>/StaticFiles/images/1.jpg

怎么实现?

思路

请求上下文肯定包含了信息能够区分出用户,比如 Session/Cookie、二级域名等,可以通过它来反向映射出静态文件路径。

例如:

二级域名静态文件路径
a.mycompany.comc:\\abc\\
b.mycompany.comd:\\xyz\\123

IFileProvider 接口实现中,我们获取不到当前请求上下文,但是中间件可以。

查看 UseStaticFiles 源代码,它使用的是 StaticFileMiddleware 中间件:

public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app, StaticFileOptions options)

    ...

    return app.UseMiddleware<StaticFileMiddleware>(Options.Create(options));

查看 StaticFileMiddleware 源代码[1],它的关键实现是这个TryServeStaticFile 方法:

public class StaticFileMiddleware

    ...

    private Task TryServeStaticFile(HttpContext context, string? contentType, PathString subPath)
    
        var fileContext = new StaticFileContext(context, _options, _logger, 
_fileProvider, contentType, subPath);
 
        if (!fileContext.LookupFileInfo())
        
            _logger.FileNotFound(fileContext.SubPath);
        
        else
        
            // If we get here, we can try to serve the file
            return fileContext.ServeStaticFile(context, _next);
        
 
        return _next(context);
    

具体如何获取静态文件是依赖_fileProvider,因此,我们只需要替换 _fileProvider,换成根据请求上下文获取对应 PhysicalFileProvider 的方法即可。

实现

创建 MyiostaticFileMiddleware,复制 StaticFileMiddleware 的原始代码,仅仅修改 TryServeStaticFile 方法:

public class MyIOStaticFileMiddleware

    ...

    private Task TryServeStaticFile(HttpContext context, string? contentType, PathString subPath)
    
        var fileContext = new StaticFileContext(context, _options, _logger, 
GetPhysicalFileProvider(context), contentType, subPath);
 
        ...
 
        return _next(context);
    

然后根据 context 获取对应的 PhysicalFileProvider 进行处理:

private IFileProvider GetPhysicalFileProvider(HttpContext context)

    //实际可从数据库获取
    if (context.Request.Host.Host.StartsWith("a.mycompany.com"))
    
        return new PhysicalFileProvider(@"c:\\abc");
    
    if (context.Request.Host.Host.StartsWith("b.mycompany.com"))
    
        return new PhysicalFileProvider(@"d:\\xyz\\123");
    
    
    ...

使用

按如下方式配置静态文件中间件:

app.UseMiddleware<MyIOStaticFileMiddleware>();

运行效果如图:

结论

今天,我们通过自定义 StaticFileMiddleware,实现了根据请求上下文动态设置静态文件存储目录。

想了解更多内容,请关注我的个人公众号”My IO“

参考资料

[1]

源代码: https://github.com/dotnet/aspnetcore/blob/main/src/Middleware/StaticFiles/src/StaticFileMiddleware.cs

以上是关于根据请求上下文动态设置静态文件存储目录的主要内容,如果未能解决你的问题,请参考以下文章

怎么实现动态设置静态文件存储目录?

Nginx与Tomcat实现请求动态数据与请求静态资源的分离

expressjs可以动态设置静态目录吗

Django静态文件404

Android M 动态权限获取

PHP静态变量与动态变量的区别