Asp.Net Core 中的“虚拟目录”实现

 更新时间:2021年9月22日 10:00  点击:1357

写在前面

  现在部署Asp.Net Core应用已经不再限制于Windows的IIS上,更多的是Docker容器、各种反向代理来部署。也有少部分用IIS部署的,IIS部署确实是又快又简单,图形化操作三下五除二就可以发布好一个系统了。在过去Asp.Net MVC 项目部署的时候,还常常使用IIS一个功能——虚拟目录。

虚拟目录可以直接定位到非项目的其他路径,将路径作为网站的一部分,可实现上传文件保存到其他盘符或间接的使用项目以外的静态文件。在Asp.Net MVC中从虚拟路径中存取文件也很简单,如Server.MapPath("~/Upload/liohuang.jpg");

但在Asp.Net Core上不同,它被抽象出一个“文件系统”,也就是FileProvider。FileProvider是对所有实现了IFileProvider接口的所有类型以及对应对象的统称,在Artech蒋老师的《.NET Core的文件系统[2]:FileProvider是个什么东西?》文章中已经透析了,这里不在罗里吧嗦了。

这篇文章要解决的内容是:Asp.Net Core应用中,如何优雅的使用“虚拟目录”。

实操

  首先,新建一个.Net Core WebApi空项目部署在D盘,“虚拟目录”假设物理路径在F盘,分别创建三个测试目录:F:/test1、F:/test2和F:/test3,目录里分别存放对应的文件1/2/3.jpg和mybook.txt。

读取虚拟目录文件

  在Startup.ConfigureServices注入IFileProvider:

services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test1"));

新建一个控制器,读取mybook.txt中的内容:

[ApiController]
 [Route("[controller]/[action]")]
 public class LioHuangController : ControllerBase
 {
  [HttpGet]
  public object GetFiles([FromServices]IFileProvider fileProvider)
  {
   var file = fileProvider.GetFileInfo("mybook.txt");
   if (file.Exists)
   {
    return ReadTxtContent(file.PhysicalPath);
   }
   return 0;
  }

  /// <summary>
  /// 读取文本 (原文地址:https://www.cnblogs.com/EminemJK/p/13362368.html)
  /// </summary>
  private string ReadTxtContent(string Path)
  {
   if (!System.IO.File.Exists(Path))
   {
    return "Not found!";
   }
   using (StreamReader sr = new StreamReader(Path, Encoding.UTF8))
   {
    StringBuilder sb = new StringBuilder();
    string content;
    while ((content = sr.ReadLine()) != null)
    {
     sb.Append(content);
    }
    return sb.ToString();
   }
  }
 }

访问接口,接口读取文件之后,返回内容:

IFileProvider接口采用目录来组织文件,并统一使用IFileInfo接口来表示,PhysicalPath表示文件的物理路径。

public interface IFileInfo
 {
  bool Exists { get; }
  bool IsDirectory { get; }
  DateTimeOffset LastModified { get; }
  string Name { get; }
  string PhysicalPath { get; }
  Stream CreateReadStream();
 }

如多个虚拟目录,怎么处理?简单,注入多个IFileProvider即可,

 services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test1"));
   services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test2"));
   services.AddSingleton<IFileProvider>(new PhysicalFileProvider("F:\\test3")); 

代码修改为:

  public object GetFiles([FromServices] IEnumerable<IFileProvider> fileProviders)

IEnumerable<IFileProvider> fileProviders接口数组将会有三个,按注入的顺序对应不同的目录。当然,注入IFileProvider的时候,就可以封装一层了,下面再讲。

另外,有的说直接ReadTxtContent("F:\test1\mybook.txt");不香吗?香,Asp.Net Core的访问权限要比Asp.Net MVC之前老版本项目要高许多,确实是可以直接读取项目以外的文件,但是并不适合直接去访问,除非说你只有一个地方使用到,那么就可以直接读取,但静态的文件的访问,就访问不到了,仅仅是后台读取而已。所以统一使用IFileProvider来约束,代码的可维护性要高许多。

静态文件访问

  在Startup.Configure设置静态文件目录,即可:

app.UseStaticFiles(new StaticFileOptions()
   {
    FileProvider = new PhysicalFileProvider("F:\\test1"),
    RequestPath = "/test"
   });;
  app.UseStaticFiles(new StaticFileOptions()
   {
    FileProvider = new PhysicalFileProvider("F:\\test2"),
    RequestPath = "/test"
   });
  app.UseStaticFiles(new StaticFileOptions()
   {
    FileProvider = new PhysicalFileProvider("F:\\test3"),
    RequestPath = "/test"
   });

FileProvider同上面所说的,设置好物理路径的根目录,RequestPath则是访问路径的前缀,必须是斜杆“/”开头,访问地址前缀则为:https://localhost:5001/test/。设置好之后,就可以访问项目以外的路径了。

如在IIS部署的时候 ,可以直接忽略IIS中的虚拟目录设置,完完全全可以通过注入的配置来设置达到“虚拟目录”的效果。

简化配置

  为了方便达到真实项目中可以直接使用,那么就要设置为可配置的:

在appsettings.json中设置:

{
 "Logging": {
 "LogLevel": {
  "Default": "Information",
  "Microsoft": "Warning",
  "Microsoft.Hosting.Lifetime": "Information"
 }
 },
 "AllowedHosts": "*",

 "VirtualPath": [
 {
  "RealPath": "F:\\test1", //真实路径
  "RequestPath": "/test",
  "Alias": "first"
 },
 {
  "RealPath": "F:\\test2", //真实路径
  "RequestPath": "/test",
  "Alias": "second"
 },
 {
  "RealPath": "F:\\test3", //真实路径
  "RequestPath": "/test",
  "Alias": "third"
 }
 ]
}

创建对应的实体映射:

public class VirtualPathConfig
 {
  public List<PathContent> VirtualPath { get; set; }
 }

 public class PathContent
 {
  public string RealPath { get; set; }

  public string RequestPath { get; set; }

  public string Alias { get; set; }
 }

在PhysicalFileProvider上封装一层,加入别名便于获取:

public class MyFileProvider : PhysicalFileProvider
  {
    public MyFileProvider(string root, string alias) : base(root)
    {
      this.Alias = alias;
    }

    public MyFileProvider(string root, Microsoft.Extensions.FileProviders.Physical.ExclusionFilters filters, string alias) : base(root, filters)
    {
      this.Alias = alias;
    }

    /// <summary>
    /// 别名
    /// </summary>
    public string Alias { get; set; }
  }

调整Startup.ConfigureServices和Startup.Configure:

public void ConfigureServices(IServiceCollection services)
    {
      services.AddControllers();
      services.Configure<VirtualPathConfig>(Configuration);

      var config = Configuration.Get<VirtualPathConfig>().VirtualPath;
      config.ForEach(f => 
      {
        services.AddSingleton(new MyFileProvider(f.RealPath,f.Alias));
      });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      var config = Configuration.Get<VirtualPathConfig>().VirtualPath;
      config.ForEach(f =>
      {
        app.UseStaticFiles(new StaticFileOptions()
        {
          FileProvider = new PhysicalFileProvider(f.RealPath),
          RequestPath =f.RequestPath
        });
      });
       
      app.UseRouting();
      app.UseAuthorization();
      app.UseEndpoints(endpoints =>
      {
        endpoints.MapControllers();
      });
    }

最后,调整调用方式,即可。

[HttpGet]
    public object GetFiles([FromServices] IEnumerable<MyFileProvider> fileProviders)
    {
      var file = fileProviders.FirstOrDefault(x=>x.Alias=="first").GetFileInfo("mybook.txt");
      if (file.Exists)
      {
        return ReadTxtContent(file.PhysicalPath);
      }
      return 0;
    }

最后

  物理文件系统的抽象通过PhysicalFileProvider这个FileProvider来实现,借助IFileProvider的特点,其实可以扩展实现轻量“云盘”的功能了,而不仅仅只是实现IIS虚拟目录功能。搞定,今晚不加班!

到此这篇关于Asp.Net Core 中的“虚拟目录”实现的文章就介绍到这了,更多相关Asp.Net Core 虚拟目录内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • ASP.NET购物车实现过程详解

    这篇文章主要为大家详细介绍了ASP.NET购物车的实现过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • .NET Core下使用Kafka的方法步骤

    这篇文章主要介绍了.NET Core下使用Kafka的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • 在ASP.NET 2.0中操作数据之七十二:调试存储过程

    在开发过程中,使用Visual Studio的断点调试功能可以很方便帮我们调试发现程序存在的错误,同样Visual Studio也支持对SQL Server里面的存储过程进行调试,下面就让我们看看具体的调试方法。...2021-09-22
  • 详解.NET Core 3.0 里新的JSON API

    这篇文章主要介绍了详解.NET Core 3.0 里新的JSON API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • ASP.NET Core根据环境变量支持多个 appsettings.json配置文件

    这篇文章主要介绍了ASP.NET Core根据环境变量支持多个 appsettings.json配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • 记一次EFCore类型转换错误及解决方案

    这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
  • 详解ASP.NET Core 中基于工厂的中间件激活的实现方法

    这篇文章主要介绍了ASP.NET Core 中基于工厂的中间件激活的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22
  • asp.net通过消息队列处理高并发请求(以抢小米手机为例)

    这篇文章主要介绍了asp.net通过消息队列处理高并发请求(以抢小米手机为例),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • Underscore源码分析

    Underscore 是一个 JavaScript 工具库,它提供了一整套函数式编程的实用功能,但是没有扩展任何 JavaScript 内置对象。这篇文章主要介绍了underscore源码分析相关知识,感兴趣的朋友一起学习吧...2016-01-02
  • ASP.NET单选按钮控件RadioButton常用属性和方法介绍

    RadioButton又称单选按钮,其在工具箱中的图标为 ,单选按钮通常成组出现,用于提供两个或多个互斥选项,即在一组单选钮中只能选择一个...2021-09-22
  • ASP.NET 2.0中的数据操作:使用两个DropDownList过滤的主/从报表

    在前面的指南中我们研究了如何显示一个简单的主/从报表, 该报表使用DropDownList和GridView控件, DropDownList填充类别,GridView显示选定类别的产品. 这类报表用于显示具有...2016-05-19
  • 详解.NET Core 使用HttpClient SSL请求出错的解决办法

    这篇文章主要介绍了.NET Core 使用HttpClient SSL请求出错的解决办法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22
  • ASP.NET中iframe框架点击左边页面链接 右边显示链接页面内容

    这篇文章主要介绍了ASP.NET中iframe框架点击左边页面链接,右边显示链接页面内容的实现代码,感兴趣的小伙伴们可以参考一下...2021-09-22
  • 创建一个完整的ASP.NET Web API项目

    ASP.NET Web API具有与ASP.NET MVC类似的编程方式,ASP.NET Web API不仅仅具有一个完全独立的消息处理管道,而且这个管道比为ASP.NET MVC设计的管道更为复杂,功能也更为强大。下面创建一个简单的Web API项目,需要的朋友可以参考下...2021-09-22
  • ASP.NET连接MySql数据库的2个方法及示例

    这篇文章主要介绍了ASP.NET连接MySql数据库的2个方法及示例,使用的是MySQL官方组件和ODBC.NET,需要的朋友可以参考下...2021-09-22
  • Asp.Net使用Bulk实现批量插入数据

    这篇文章主要介绍了Asp.Net使用Bulk实现批量插入数据的方法,对于进行asp.net数据库程序设计非常有借鉴价值,需要的朋友可以参考下...2021-09-22
  • Asp.net中获取DataTable选择第一行某一列值

    这篇文章主要介绍了获取DataTable选择第一行某一列值,需要的朋友可以参考下...2021-09-22
  • Asp.net动态生成html页面的方法分享

    这篇文章介绍了Asp.net动态生成html页面的方法,有需要的朋友可以参考一下...2021-09-22
  • ASP.Net中的async+await异步编程的实现

    这篇文章主要介绍了ASP.Net中的async+await异步编程的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • .net EF Core专题:EF Core 读取数据时发生了什么?

    这篇文章主要介绍了EF Core 读取数据的的相关知识,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2021-09-22