Converting a URI path to a relative file system path in .NET

后端 未结 4 781
故里飘歌
故里飘歌 2020-12-30 18:36

How do I convert an absolute or relative URI path (e.g. /foo/bar.txt) to a (segmentwise) corresponding relative file system path (e.g. foo\\bar.txt

相关标签:
4条回答
  • 2020-12-30 19:03

    I figured out this way to produce a full absolute file system path from a relative or absolute URI and a base path.

    With:

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

    From a relative URI:

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

    From an absolute URI:

    // baseUri is a URI used to derive a relative URI
    Uri relativeUri = baseUri.MakeRelativeUri(absoluteUri);
    string filePath = new Uri(basePathUri, relativeUri).AbsolutePath;
    
    0 讨论(0)
  • 2020-12-30 19:13

    Have you already tried Server.MapPath?
    or Uri.LocalPath property? Something like following :

    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);
    }
    
    0 讨论(0)
  • 2020-12-30 19:17

    Not all have access to server.MapPath due to backend or framework changes, and there are lot's of way one of them is could be like this

    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;
    }
    

    after this you just do:

    switch (IsMappedTo(url))
    {
        case FileLocation.NotSet:
            break;
    
        case FileLocation.Disk:
            break;
    
        case FileLocation.Resource:
    
            break;
    }
    
    0 讨论(0)
  • 2020-12-30 19:23

    You can do this:

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

    See MSDN for details

    0 讨论(0)
提交回复
热议问题