Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core 如何在asp.net内核中更改控制器中的静态文件位置?_Asp.net Core_.net Core - Fatal编程技术网

Asp.net core 如何在asp.net内核中更改控制器中的静态文件位置?

Asp.net core 如何在asp.net内核中更改控制器中的静态文件位置?,asp.net-core,.net-core,Asp.net Core,.net Core,我知道我们可以在Configure方法中设置FileProvider来为其他位置文件提供服务器: app.UseStaticFiles(新的StaticFileOptions { FileProvider=new PhysicalFileProvider(Path.Combine(env.WebRootPath,“images”), RequestPath=“/MyImages” }); 我想知道如何更改控制器中的文件提供程序文件位置,因为我想通过用户输入重置路径。重置路径涉及传递参数,但此中

我知道我们可以在
Configure
方法中设置
FileProvider
来为其他位置文件提供服务器:

app.UseStaticFiles(新的StaticFileOptions
{
FileProvider=new PhysicalFileProvider(Path.Combine(env.WebRootPath,“images”),
RequestPath=“/MyImages”
});

我想知道如何更改控制器中的
文件提供程序
文件位置,因为我想通过用户输入重置路径。

重置路径涉及传递参数,但此中间件UseStaticFiles不提供
上下文
,以从请求中获取参数。虽然可以通过自定义中间件重置路径,但这将使原始设计更加复杂。因此,您可以使用OpenRead方法将图片读入文件流

public IActionResult get(string filePath)
    {
        
        var image = System.IO.File.OpenRead(webHostEnvironment.WebRootPath + filePath);
        return File(image, "image/jpeg");
    }

这将使图片显示在视图中,而不是下载。

在您的场景中,我认为您应该有一个不同web根路径的预设,供用户选择。这有什么意义?因为通常根路径应该存在并且已经包含一些内容(就像
wwwroot
)。如果这符合您的需要,我们可以提供如下简单解决方案:

//inside Startup.Configure

app.UseWhen(context => {
              var wr = context.Request.Cookies["wwwroot"];
              return string.IsNullOrEmpty(wr) || wr == "wwwroot";
            }, subApp => {
              subApp.UseStaticFiles();
}).UseWhen(context => {
              var wr = context.Request.Cookies["wwwroot"];
              return wr == "YAwwwroot";
           }, subApp => {
              subApp.UseStaticFiles(new StaticFileOptions
              {
                FileProvider = new PhysicalFileProvider(Path.Combine(HostingEnvironment.ContentRootPath, "YAwwwroot"))
              });
});
上面的代码使用
UseWhen
将静态文件中间件与先决条件(事先已知)动态交换。我只是把它作为一个简单的例子来说明它是多么简单。要使用的另一个根路径是
YAwwwroot
。使用
Cookies
只是为了演示,您可以通过任何其他方式(例如:保持活动根路径状态的单例服务或选项)从
HttpContext
访问数据。如您所见,我们必须事先知道相应地编写
UseWhen
代码的根路径。您还可以编写自己的扩展方法,以避免重复
UseWhen
(因此,如果您有许多根路径,则不必重复许多
UseWhen

在某些控制器操作中,您可以设置活动根路径(这里与上面的代码结合使用,我们通过cookies设置活动根路径):

现在,如果您真的希望用户设置的活动根路径是动态的(当然完全由用户控制)。我们需要为静态文件创建一个自定义中间件。然而,我们不需要重新实施太多。我们可以重用
静态文件中间件
。默认的中间件是一个单例,它只捕获一次
StaticFileOptions
。这就是为什么即使您可以更新
StaticFileOptions
,它也不会有任何效果

我们可以在这里为静态文件实现两种中间件:作用域中间件和单例中间件

它们的工作方式相同,对于每个请求,
StaticFileOptions
的最新值将传递给默认的
StaticFileMiddleware
(在实例化它时)。因此,控制器操作可以直接更新
StaticFileOptions
,以更改静态文件的根路径

以下是作用域版本:

public class ScopedStaticFileMiddleware : IMiddleware
{
    readonly IHostingEnvironment _hostingEnvironment;
    readonly IOptions<StaticFileOptions> _staticFileOptions;
    readonly ILoggerFactory _loggerFactory;
    public ScopedStaticFileMiddleware(IHostingEnvironment hostingEnvironment,
        IOptions<StaticFileOptions> staticFileOptions,
        ILoggerFactory loggerFactory)
    {
        _hostingEnvironment = hostingEnvironment;
        _staticFileOptions = staticFileOptions;
        _loggerFactory = loggerFactory;
    }

    public Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        //here we create the default static file middleware
        var staticFileMiddleware = new StaticFileMiddleware(next, _hostingEnvironment, _staticFileOptions, _loggerFactory);
        return staticFileMiddleware.Invoke(context);
    }
}

注意:上面的代码不负责检查绝对根路径是否存在或是否应该创建绝对根路径。这是你的责任。

哇,太棒了。非常感谢你,国王
public class ScopedStaticFileMiddleware : IMiddleware
{
    readonly IHostingEnvironment _hostingEnvironment;
    readonly IOptions<StaticFileOptions> _staticFileOptions;
    readonly ILoggerFactory _loggerFactory;
    public ScopedStaticFileMiddleware(IHostingEnvironment hostingEnvironment,
        IOptions<StaticFileOptions> staticFileOptions,
        ILoggerFactory loggerFactory)
    {
        _hostingEnvironment = hostingEnvironment;
        _staticFileOptions = staticFileOptions;
        _loggerFactory = loggerFactory;
    }

    public Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        //here we create the default static file middleware
        var staticFileMiddleware = new StaticFileMiddleware(next, _hostingEnvironment, _staticFileOptions, _loggerFactory);
        return staticFileMiddleware.Invoke(context);
    }
}
//inside Startup.ConfigureServices
services.AddScoped<ScopedStaticFileMiddleware>();

//inside Startup.Configure (replacing app.UseStaticFiles)
app.UseMiddleware<ScopedStaticFileMiddleware>();
public class ScopedOptionsStaticFileMiddleware
{
    readonly RequestDelegate _next;
    readonly IHostingEnvironment _hostingEnvironment;        
    readonly IOptions<StaticFileOptions> _staticFileOptions;
    readonly ILoggerFactory _loggerFactory;
    public ScopedOptionsStaticFileMiddleware(RequestDelegate next,
        IHostingEnvironment hostingEnvironment, 
        IOptions<StaticFileOptions> staticFileOptions,
        ILoggerFactory loggerFactory)             
    {
        _next = next;
        _hostingEnvironment = hostingEnvironment;
        _staticFileOptions = staticFileOptions;
        _loggerFactory = loggerFactory;            
    }

    public Task Invoke(HttpContext context)
    {
        //we create the default middleware each time processing a request
        //so the latest static file options is always used
        var defaultMiddleware = new StaticFileMiddleware(_next, _hostingEnvironment, 
                                                         _staticFileOptions, _loggerFactory);
        return defaultMiddleware.Invoke(context);
    }        
}  
//inside Startup.Configure
app.UseMiddleware<ScopedOptionsStaticFileMiddleware>();
//inject IOptions<StaticFileOptions> and get its value into _staticFileOptions
//inject IWebHostEnvironment as _environment
...

public IActionResult SetStaticFileRoot(string root) {
      root = root ?? "wwwroot";     
      //create a new file provider with the new root path       
      _staticFileOptions.FileProvider = new PhysicalFileProvider(Path.Combine(_environment.ContentRootPath, root));            
      return Ok(root);
}