我有指向 IIS 中某些文件服务器的虚拟目录。我了解到 ASP.NET Core 无法“看到”IIS 中的虚拟目录,因为它在 Kestral 上运行。
有人告诉我解决方法是使用 app.UseFileServer:
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(@"\\server\path"),
RequestPath = new PathString("/MyPath"),
EnableDirectoryBrowsing = true
});
我设置了它,当我在浏览器地址栏中输入/MyPath 时它就起作用了。 但是,我希望能够在 Controller 中获取物理路径。
类似于:
//Server.Map path no longer exists in ASP.NET Core...
var filePath = Server.MapPath("/MyPath");
var fileName = "MyFile.txt";
System.IO.File.OpenRead(Path.Combine(filePath , fileName));
有没有办法通过提供我在 app.UseFileServer 中设置的 RequestPath 来获取物理路径?
最佳答案
这个问题的核心是在 Controller 中访问正确的 IFileProvider(它指向目录的物理路径)。
您可以通过在自定义服务中配置这些路径来解决此问题,以便您可以在任何地方访问它们:
- 在您的 Configure() 方法中设置 UseFileServer
- 在你的 Controller 等中
我有一些代码可以演示您如何进行此操作:
服务及便利方式
首先,创建一个自定义服务,它将保存您的 FileServerOptions,可以通过 UseFileServer() 或您的 Controller 访问。我选择了它们的列表,因此您可以添加多个路径。
public interface IFileServerProvider
{
/// <summary>
/// Contains a list of FileServer options, a combination of virtual + physical paths we can access at any time
/// </summary>
IList<FileServerOptions> FileServerOptionsCollection { get; }
/// <summary>
/// Gets the IFileProvider to access a physical location by using its virtual path
/// </summary>
IFileProvider GetProvider(string virtualPath);
}
/// <summary>
/// Implements IFileServerProvider in a very simple way, for demonstration only
/// </summary>
public class FileServerProvider : IFileServerProvider
{
public FileServerProvider(IList<FileServerOptions> fileServerOptions)
{
FileServerOptionsCollection = fileServerOptions;
}
public IList<FileServerOptions> FileServerOptionsCollection { get; }
public IFileProvider GetProvider(string virtualPath)
{
var options = FileServerOptionsCollection.FirstOrDefault(e => e.RequestPath == virtualPath);
if (options != null)
return options.FileProvider;
throw new FileNotFoundException($"virtual path {virtualPath} is not registered in the fileserver provider");
}
}
然后,为了方便起见,您还可以添加一个扩展方法,该方法将使用上述服务中的选项调用 UseFileServer 中间件:
/// <summary>
/// Wrapper for UseFileServer to easily use the FileServerOptions registered in the IFileServerProvider
/// </summary>
public static class FileServerProviderExtensions
{
public static IApplicationBuilder UseFileServerProvider(this IApplicationBuilder application, IFileServerProvider fileServerprovider)
{
foreach (var option in fileServerprovider.FileServerOptionsCollection)
{
application.UseFileServer(option);
}
return application;
}
}
启动方法
现在,您只需将 IFileServerProvider 注册到您选择的路径 (1) 并将其交给方便的方法来实际使用它们 (2)。
(1) 首先,使用您选择的路径将 IFileServerProvider 注册为单例服务:
public void ConfigureServices(IServiceCollection services)
{
//Add our IFileServerProvider implementation as a singleton
services.AddSingleton<IFileServerProvider>(new FileServerProvider(
new List<FileServerOptions>
{
new FileServerOptions
{
FileProvider = new PhysicalFileProvider(@"D:\\somepath"),
RequestPath = new PathString("/OtherPath"),
EnableDirectoryBrowsing = true
},
new FileServerOptions
{
FileProvider = new PhysicalFileProvider(@"\\server\path"),
RequestPath = new PathString("/MyPath"),
EnableDirectoryBrowsing = true
}
}));
// Add framework services.
services.AddMvc();
}
(2) 然后通过调用之前创建的扩展方法在 UseFileServer 中实际使用它们。请注意 Configure 方法中的额外参数 IFileServerProvider fileServerprovider
:
// Note: accessing the IFileServerProvider implemantion here by adding it
// in the arguments list!
public void Configure(IApplicationBuilder app, IFileServerProvider fileServerprovider)
{
//call convenience method which adds our FileServerOptions from
// the IFileServerProvider service
app.UseFileServerProvider(fileServerprovider);
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
用法
现在,当您浏览到路径/MyPath 或/OtherPath 时,您应该像以前一样得到一个目录列表。
但是,因为我们在服务中整理了所有内容,所以现在更容易在 Controller 中以编程方式访问这些路径:
public class HomeController : Controller
{
private IFileServerProvider _fileServerProvider;
public HomeController(IFileServerProvider fileServerProvider)
{
_fileServerProvider = fileServerProvider;
}
public IActionResult Index()
{
var fileProvider = _fileServerProvider.GetProvider("/MyPath");
var fileInfo = fileProvider.GetFileInfo("MyFile.txt");
using (var stream = System.IO.File.OpenRead(fileInfo.PhysicalPath))
{
string contents = new StreamReader(stream).ReadToEnd();
}
return View();
}
}
这段代码或许可以写成更抽象、命名更恰当的版本,但它展示了解决您的问题的有效解决方案。
关于c# - 在 ASP.NET Core 中设置 app.UseFileServer 后获取 PhysicalPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43190824/