【问题标题】:Converting a URI path to a relative file system path in .NET将 URI 路径转换为 ​​.NET 中的相对文件系统路径
【发布时间】:2011-01-27 09:10:09
【问题描述】:

如何在 .NET 中将绝对或相对 URI 路径(例如 /foo/bar.txt)转换为(分段)对应的相对文件系统路径(例如 foo\bar.txt)?

我的程序不是 ASP.NET 应用程序。

【问题讨论】:

  • 以相对 URI 路径为例对我来说可能更有意义。

标签: c# .net path uri


【解决方案1】:

由于后端或框架更改,并非所有人都可以访问 server.MapPath,并且有很多方式其中之一可能是这样的

public enum FileLocation
{
    NotSet,
    Disk,
    Resource,
}

private static readonly string[] FileExtenstions = new[] {
    ".js"
    ,".ts"
    ,".vue"
    ,".css"
    ,".jpg"
    ,".png"
    ,".gif"
    ,".ico"
    ,".svg"
    ,".ttf"
    ,".eot"
    ,".ttf"
    ,".woff"
    ,".woff2"
    ,".mp4"
    ,".mp3"
    ,".emf"
};

public FileLocation IsMappedTo(Uri uri)
{
    if (uri is null)
    {
        throw new ArgumentNullException(nameof(uri));
    }
    //make sure we support .net default URI contract
    if (uri.IsFile)
        return FileLocation.Disk;

    //now assume you are looking in a web application
    var path = uri.AbsolutePath;
    if (path.Length == 0 || path.Equals("/",StringComparison.Ordinal) || path.Length< FileExtenstions.Min(s=>s.Length))
        return FileLocation.NotSet;

    //get the directory normally one would use IWebHostEnvironment.ContentRootPath different versions .net will have other methods
    var dir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");

    //get all resources names from the assembly hosting this class out side if the loop from this assembly you can also use
    //you can also use GetManifestResourceNames() to use the web application's assembly
    var resourceNames = new HashSet<string>(this.GetType().Assembly.GetManifestResourceNames());
    var entryAssembly = Assembly.GetEntryAssembly();
    if (entryAssembly != null && entryAssembly != this.GetType().Assembly)
    {
        foreach (var entry in entryAssembly.GetManifestResourceNames())
        {
            if (string.IsNullOrEmpty(entry))
                resourceNames.Add(entry);
        }
    }

    for (var i = 0; i < FileExtenstions.Length; i++)
    {
        if (FileExtenstions[i].Equals(path[FileExtenstions[i].Length..], StringComparison.OrdinalIgnoreCase) || path.Contains(FileExtenstions[i], StringComparison.OrdinalIgnoreCase))
        {
            //exists on disk
            if (File.Exists(Path.Combine(dir, path.Replace("/", @"\", StringComparison.Ordinal))))
                return FileLocation.Disk;

            //has a file as an embedded resource with the same name (ignores the path) so you might have duplicates names
            if (resourceNames.Any(a => a.EndsWith(path.Split('/')[^1], StringComparison.OrdinalIgnoreCase)))
                return FileLocation.Resource;
        }
    }

    return FileLocation.NotSet;
}

在此之后,您只需:

switch (IsMappedTo(url))
{
    case FileLocation.NotSet:
        break;

    case FileLocation.Disk:
        break;

    case FileLocation.Resource:

        break;
}

【讨论】:

    【解决方案2】:

    您是否已经尝试过Server.MapPath
    Uri.LocalPath 财产?类似于以下内容:

    string uriString = "file://server/filename.ext";
    // Lesson learnt - always check for a valid URI
    if(Uri.IsWellFormedUriString(uriString))
    {
        Uri uri = new Uri(uriString);
        Console.WriteLine(uri.LocalPath);
    }
    

    【讨论】:

    • @Binary,@Gareth,很高兴能帮到你。
    • 好吧,我不得不修改这段代码来使用这个片段而不是 Console.WriteLine(uri.LocalPath + Uri.UnescapeDataString(uri.Fragment)) 这是由于文件名中的 # 字符
    【解决方案3】:

    我想出了这种方法,可以从相对或绝对 URI 和基本路径生成完整的绝对文件系统路径。

    与:

    Uri basePathUri = new Uri(@"C:\abc\");
    

    来自相对 URI:

    string filePath = new Uri(basePathUri, relativeUri).AbsolutePath;
    

    来自绝对 URI:

    // baseUri is a URI used to derive a relative URI
    Uri relativeUri = baseUri.MakeRelativeUri(absoluteUri);
    string filePath = new Uri(basePathUri, relativeUri).AbsolutePath;
    

    【讨论】:

      【解决方案4】:

      你可以这样做:

      var localPath = Server.MapPath("/foo/bar.txt");
      

      See MSDN for details

      【讨论】:

      • 我的程序不是 ASP.NET 应用程序,我如何访问 Server 对象?
      • @acdx - 我很困惑……相对于什么,一个正在运行的应用程序?你的问题被标记为uri,所以如果不是网络,我很困惑,解释一下?
      • 我想获取一个相对文件路径,例如foo\bar.txt,我可以将其传递给Path.Combine 以创建绝对文件路径。
      • @acdx - 相对于...相对于 what 是一个问题,您问的是 URI,但说它不是网络...这是没有意义的,需要澄清一下。对于初学者,如果不是 Web 应用程序,您正在运行什么
      • 我的应用程序是一个常规的 .NET 控制台应用程序。我想将 URI 映射到文件系统路径。我认为最简单的方法是将 URI 路径转换为相对文件系统路径,然后将其传递给 Path.Combine 以及像 `C:\abc` 这样的基本路径以形成绝对文件系统路径。关于术语,根据定义,相对路径不包含与其相关的信息。
      猜你喜欢
      • 2016-12-11
      • 2015-02-22
      • 2018-05-28
      • 1970-01-01
      • 2017-08-01
      • 2011-11-07
      • 2011-05-02
      相关资源
      最近更新 更多