获取虚拟目录中文件的本地路径

2024-04-15

我有一个 ASP.NET Core 3.0 MVC 应用程序,其中包含图像。例如。,

http://foo.bar/images/image.jpg

现在,文件夹images is a 虚拟目录映射到网络驱动器,例如\\192.168.1.1\images.

问题:

用什么方法转信息/images/image.jpg into \\192.168.1.1\images\image.jpg?我需要检索物理路径文件的相对网络路径.

在 ASP.NET Web 窗体中,这可以通过类似的方法来完成Server.MapPath("~/images/image.jpg"),但是ASP.NET Core中不存在这个方法HttpContext不再了。


正如所指出的@阿克谢·冈卡 https://stackoverflow.com/users/4018180/akshay-gaonkar在评论中,微软已明确评估并拒绝了 ASP.NET Core 中的此功能(参考 https://github.com/dotnet/aspnetcore/issues/3824):

我们没有实施此计划的计划。这些概念在 ASP.NET Core 中并没有真正对应。 URL 本质上并不基于任何目录结构。每个组件都有可能映射到目录的约定,但这不是可以概括的。

而同时建议使用一种解决方法IFileProvider https://github.com/dotnet/aspnetcore/issues/3824#issuecomment-400107781,它实际上不适用于虚拟目录。你什么can然而,要做的是建立一个映射服务来转换基本路径,并可选择查询 IIS 以动态检索这些映射,正如我将在下面讨论的那样。

背景

这种限制源于这样一个事实:ASP.NET Core 不再依赖于 IIS,而是依赖于抽象层(例如,IWebHostEnvironment) 与网络服务器对话;由于默认的 ASP.NET Core Kestrel Web 服务器充当反向代理(参考 https://github.com/dotnet/aspnetcore/issues/3824#issuecomment-387476614):

那会很艰难。我认为我们甚至不可能在当前的反向代理架构中实现这一点。您将必须维护一个手动映射表。

请记住,虚拟目录(或者更重要的是虚拟应用程序)的概念是专门针对 IIS 作为 Web 服务器的。

解决方法

不幸的是,正如前面的摘录中提到的,您唯一真正的选择是在虚拟目录与其物理位置之间创建映射,然后创建一个为您处理翻译的服务。

以下是如何实现这一目标的基本概念验证 - 当然,您可能需要更健壮的生产代码。

界面

这引入了可用于依赖项注入和测试目的的抽象。我一直坚持MapPath()为了与旧版 Web 表单签名保持一致。

public interface IVirtualFileProvider
{
    string MapPath(string path);
}

Service

接口的具体实现可能会从一个配置文件 https://stackoverflow.com/a/64248257/3025856、数据库——甚至是微软网络管理库 https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.administration.virtualdirectorycollection?view=iis-dotnet。然而,对于这个概念验证,我只是将它们硬编码到提供程序中:

public class VirtualFileProvider: IVirtualFileProvider
{

    // Store dependencies
    private readonly string _webRootPath;

    // Map virtual directories
    private readonly Dictionary<string, string> _virtualDirectories = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) {
        { "Images", @"\\192.168.1.1\images" }
    };

    public VirtualFileProvider(string webRootPath) {
      _webRootPath = webRootPath;
    }

    public string MapPath(string path)
    {

        // Validate path
        if (String.IsNullOrEmpty(path) || !path.StartsWith("/", StringComparison.Ordinal)) {
            throw new ArgumentException($"The '{path}' should be root relative, and start with a '/'.");
        }

        // Translate path to UNC format
        path                = path.Replace("/", @"\", StringComparison.Ordinal);

        // Isolate first folder (or file)
        var firstFolder     = path.IndexOf(@"\", 1);
        if (firstFolder < 0)
        {
            firstFolder     = path.Length;
        }

        // Parse root directory from remainder of path
        var rootDirectory   = path.Substring(1, firstFolder-1);
        var relativePath    = path.Substring(firstFolder);

        // Return virtual directory
        if (_virtualDirectories.ContainsKey(rootDirectory))
        {
            return _virtualDirectories[rootDirectory] + relativePath;
        }

        // Return non-virtual directory
        return _webRootPath + @"\" + rootDirectory + relativePath;

    }

}

登记

该实现需要了解默认 Web 根目录,以便转换不在虚拟目录中的文件的路径。这可以动态检索,如所示@Pashyant Srivastava 的回答 https://stackoverflow.com/a/67570843/3025856,虽然我正在使用IWebHostEnvironment这里。这样,您就可以注册VirtualFileProvider作为具有 ASP.NET Core 依赖注入容器的单例生活方式:

public class Startup 
{

    private readonly IWebHostEnvironment _hostingEnvironment;

    public Startup(IWebHostEnvironment webHostEnvironment) 
    {
        _hostingEnvironment = webHostEnvironment;
    }

    public void ConfigureServices(IServiceCollection services)
    {

        // Add framework services.
        services.AddMvc();

        // Register virtual file provider
        services.AddSingleton<IVirtualFileProvider>(new VirtualFileProvider(_hostingEnvironment.WebRootPath));

    }

    public static void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
    {
        …
    }

}

执行

注册实现后,您可以将提供程序注入到 MVC 控制器的构造函数中,甚至直接注入到您的操作中:

public IActionResult MyAction([FromServices] IVirtualFileProvider fileProvider, string file)
    => Content(fileProvider?.MapPath(file));

局限性

上面的代码没有努力验证该文件actually存在——尽管很容易通过以下方式添加File.Exists() https://learn.microsoft.com/en-us/dotnet/api/system.io.file.exists?view=net-5.0。这显然会使通话费用更高一些。

动态映射

上述实现依赖于硬编码值。不过,正如前面提到的,微软网络管理库 https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.administration提供以编程方式与 IIS 交互的方法。这包括Application.VirtualDirectories财产 https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.administration.application.virtualdirectories?view=iis-dotnet用于从 IIS 中提取虚拟目录列表:

var directories = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var manager     = new ServerManager();
var site        = manager.Sites["Default Web Site"];
var application = site[0]; 
                
foreach (var virtualDirectory in application.VirtualDirectories)
{
    directories.Add(virtualDirectory.Path, virtualDirectory.PhysicalPath);
}

这可以与VirtualFileProvider如果需要,动态评估可用的虚拟目录。

Warning:Microsoft Web 管理库尚未更新为支持 .NET 5,并且维护对不向前兼容的 .NET Core 3.x 库的依赖关系。目前尚不清楚 Microsoft 何时或是否会发布 .NET 5 兼容版本。由于您的问题特定于 .NET Core 3.1,因此这可能不是一个紧迫的问题。但由于 .NET 5 是 .NET 的当前版本,引入对 Microsoft Web 管理库的依赖可能会带来长期风险。

结论

我知道这不是您所希望的方法。然而,根据您的具体实现,这可能是一个可接受的解决方法。显然,如果这是一个可重用的库,放置在您不了解虚拟目录的各种站点上,则需要将数据与实现分开。不过,这至少提供了一个可以使用的基本结构。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获取虚拟目录中文件的本地路径 的相关文章

  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • Visual Studio 在构建后显示假错误

    我使用的是 Visual Studio 2017 构建后 sln在调试模式下 我收到错误 但是 当我通过双击错误列表选项卡中的错误来访问错误时 错误会从页面中消失 并且错误数量也会减少 我不太确定这种行为以及为什么会发生这种情况 有超过 2
  • 使用可变参数包类型扩展的 C++ 函数调用者包装器

    我绑定了一些 API 并且绑定了一些函数签名 如下所示 static bool WrapperFunction JSContext cx unsigned argc JS Value vp 我尝试将对象和函数包装在 SpiderMonkey
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • 从 ASP .Net Web 服务访问 MSMQ 时出现权限错误

    我写了一个从消息队列读取的 Web 服务 这在卡西尼号下工作得很好 现在我已经在 IIS 下部署了该服务 当该服务尝试访问队列时 我收到一条错误消息 队列不存在或者您没有足够的权限来执行该操作 我已将 IIS 虚拟目录上的匿名访问用户设置为
  • 堆栈是向上增长还是向下增长?

    我在 C 中有这段代码 int q 10 int s 5 int a 3 printf Address of a d n int a printf Address of a 1 d n int a 1 printf Address of a
  • 使用 omp_set_num_threads() 将线程数设置为 2,但 omp_get_num_threads() 返回 1

    我有以下使用 OpenMP 的 C C 代码 int nProcessors omp get max threads if argv 4 NULL printf argv 4 s n argv 4 nProcessors atoi argv

随机推荐

  • python 对象可以有嵌套属性吗?

    我有一个定义如下的对象 class a property def prop self print hello from object prop property def prop1 self print Hello from object
  • .gitlab-ci.yml 中的规则条件是否有 AND 选项?

    我想创建一些嵌套条件 当它是合并或合并请求并且以特定名称启动 功能 时 我需要此管道才能工作 那么 作业的 唯一 选项中是否有 AND 条件 不 那里没有 你必须使用rules https docs gitlab com ee ci yam
  • 如何创建开始菜单快捷方式

    我正在构建一个自定义安装程序 如何在开始菜单中创建可执行文件的快捷方式 这是我到目前为止所想出的 string pathToExe C Program Files x86 TestApp TestApp exe string commonS
  • mysql 使用addslashes() [重复]

    这个问题在这里已经有答案了 可能的重复 mysql real escape string 能做什么 而addslashes 不能 https stackoverflow com questions 534742 what does mysq
  • 如何在 iOS 应用程序中使用 Berkeley DB?

    我想在 iOS 应用程序中使用 Berkeley DB 但我不知道如何去做 如何将 Berkeley DB 集成到 iOS 项目中 你如何通过 Objective C 与它通信 是否有任何教程或示例可以演示如何做到这一点 首先要注意的是 该
  • 是否可以在不使用 boto3 下载 S3 文件的情况下获取其内容?

    我正在研究一个从 a 中转储文件的过程Redshift数据库 并且不希望必须在本地下载文件来处理数据 我看到了Java has a StreamingObject类可以做我想要的事情 但我还没有看到类似的东西boto3 如果你有一个mybu
  • 模块“pandas”没有属性“rolling_mean”

    我正在尝试构建 ARIMA 用于异常检测 我需要找到时间序列图的移动平均值 我尝试为此使用 pandas 0 23 import pandas as pd import numpy as np from statsmodels tsa st
  • 地理编码器错误 java.io.IOException:无法解析来自服务器的响应

    Code Geocoder geocoder new Geocoder map this Locale getDefault List
  • 为什么sonar:sonar需要先安装mvn?

    官方文档http docs sonarqube org display SONAR Analyzing with Maven http docs sonarqube org display SONAR Analyzing with Mave
  • iOS:通过自定义 UITableViewCell 上的 UITextView 选择

    我有一个带有图像和 UITextView 属性的自定义 UITableViewCell 文本视图跨越到单元格的边缘 我的问题是点击文本视图未在 didSelectRowAtIndexPath 中注册 我怎样才能让我可以 点击 我的文本视图
  • Login-AzureRmAccount 命令无法从托管 C# 应用程序运行

    我正在使用 powershell 脚本登录到 azure 为此我编写了简单的命令 Login AzureRmAccount 并在单击按钮时将该脚本调用到 C 代码中 它在本地工作正常 但是当我在服务器上托管此页面时 身份验证弹出窗口未打开
  • 如何在 PHP 中打印今天的尼泊尔日期? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想以不同的日期格式回显打印尼泊尔日历日期 请看一下下面的代码 有一个 jquery 日期选择器 http sajanmaharjan c
  • 是否可以预加载和缓存视频文件而不将它们添加到 DOM?

    我正在开发一款游戏 根据得到的结果触发 30 个小视频文件中的一个 由于视频需要在用户交互后立即播放 因此理想情况下我希望预加载视频并准备好播放 我添加了 PreloadJS 对我需要的所有资源进行了排队 查看检查器中的 网络 选项卡 我可
  • ed25519.公开结果不同

    使用包https github com golang crypto tree master ed25519 https github com golang crypto tree master ed25519我正在尝试获取给定私钥的公钥 这
  • 将变量传递到 xp_cmdshell

    我在 SQL Server 中有一个存储过程 用于检查今天的备份文件 文件名中包含日期的文件 检查完毕后 将继续进行robocopy这些文件到另一个文件夹 挑战 在此文件夹中 可能存在昨天或其他日期的文件 但只需要今天的bak文件来传输 d
  • 错误域=NSOSStatusErrorDomain 代码=-12780 \"(null)\"

    当我尝试使用 AVAssetExport 导出资产时 仅在通过 Whatsapp 接收的视频上可能会出现以下错误 我找不到可行的解决方案 我还尝试实现代码来修复视频持续时间 但我没有修复它 错误是 错误域 NSOSStatusErrorDo
  • Webpack 4.编译scss分离css文件

    我试图将 scss 编译成一个单独的 css 文件 但没有成功 现在 css 与所有 js 代码一起进入到bundle js 中 我怎样才能将我的CSS分离到它自己的文件中 这是我的配置的样子 var path require path m
  • 使用 jQuery 检查链接是否仍然有效

    我创建了一个快速功能 使用 AJAX 检查页面上的每个链接 看看它们是否仍然有效 这似乎有效 但它为每个类添加了成功和错误类 如何让错误回调函数仅在 AJAX 响应为 404 时抛出 li each function this childr
  • 如何垂直对齐 IE 输入框上的文本

    I have this http jsfiddle net dVDT8 code
  • 获取虚拟目录中文件的本地路径

    我有一个 ASP NET Core 3 0 MVC 应用程序 其中包含图像 例如 http foo bar images image jpg 现在 文件夹images is a 虚拟目录映射到网络驱动器 例如 192 168 1 1 ima