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

原文链接:https://blog.csdn.net/sD7O95O/article/details/107587430

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

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

1
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 :

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[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>
    /// 读取文本
    /// </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 表示文件的物理路径。

1
2
3
4
5
6
7
8
9
public interface IFileInfo
{
    bool Exists { get; }
    bool IsDirectory { get; }
    DateTimeOffset LastModified { get; }
    string Name { get; }
    string PhysicalPath { get; }
    Stream CreateReadStream();
}

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

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

  代码修改为:

1
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设置静态文件目录,即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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/ 

设置好之后,就可以访问项目以外的路径了。

 

posted @   yinghualeihenmei  阅读(93)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2022-06-21 Global.asax文件
点击右上角即可分享
微信分享提示