根据@Tratcher的提议和
this博客文章,这里提供了一种解决方案,可以实现对大小写敏感的物理文件提供程序,您可以选择强制大小写敏感或允许任何大小写,而不受操作系统的影响。
public class CaseAwarePhysicalFileProvider : IFileProvider
{
private readonly PhysicalFileProvider _provider;
private static Dictionary<string, string> _paths;
public bool CaseSensitive { get; set; } = false;
public CaseAwarePhysicalFileProvider(string root)
{
_provider = new PhysicalFileProvider(root);
_paths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
public CaseAwarePhysicalFileProvider(string root, ExclusionFilters filters)
{
_provider = new PhysicalFileProvider(root, filters);
_paths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
public IFileInfo GetFileInfo(string subpath)
{
var actualPath = GetActualFilePath(subpath);
if(CaseSensitive && actualPath != subpath) return new NotFoundFileInfo(subpath);
return _provider.GetFileInfo(actualPath);
}
public IDirectoryContents GetDirectoryContents(string subpath)
{
var actualPath = GetActualFilePath(subpath);
if(CaseSensitive && actualPath != subpath) return NotFoundDirectoryContents.Singleton;
return _provider.GetDirectoryContents(actualPath);
}
public IChangeToken Watch(string filter) => _provider.Watch(filter);
private string GetActualFilePath(string path)
{
if (_paths.ContainsKey(path)) return _paths[path];
var currPath = _provider.Root;
var segments = path.Split(new [] { '/' }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < segments.Length; i++)
{
var part = segments[i];
var last = i == segments.Length - 1;
if (part.Equals("~")) continue;
part = last ? GetFileName(part, currPath) : GetDirectoryName(part, currPath);
if (part == null) return path;
currPath = Path.Combine(currPath, part);
segments[i] = part;
}
var actualPath = string.Join(Path.DirectorySeparatorChar, segments);
_paths.Add(path, actualPath);
return actualPath;
}
private static string GetFileName(string part, string folder) =>
new DirectoryInfo(folder).GetFiles().FirstOrDefault(file => file.Name.Equals(part, StringComparison.OrdinalIgnoreCase))?.Name;
private static string GetDirectoryName(string part, string folder) =>
new DirectoryInfo(folder).GetDirectories().FirstOrDefault(dir => dir.Name.Equals(part, StringComparison.OrdinalIgnoreCase))?.Name;
}
然后在启动类中,确保您按照以下方式为内容和Web根目录注册提供程序:
_environment.ContentRootFileProvider = new CaseAwarePhysicalFileProvider(_environment.ContentRootPath)
_environment.WebRootFileProvider = new CaseAwarePhysicalFileProvider(_environment.WebRootPath)