Absolute path back to web-relative path
Asked Answered
E

6

66

If I have managed to locate and verify the existence of a file using Server.MapPath and I now want to send the user directly to that file, what is the fastest way to convert that absolute path back into a relative web path?

Economic answered 6/8, 2008 at 8:34 Comment(0)
J
56

Perhaps this might work:

String RelativePath = AbsolutePath.Replace(Request.ServerVariables["APPL_PHYSICAL_PATH"], String.Empty);

I'm using c# but could be adapted to vb.

Jasisa answered 6/8, 2008 at 9:28 Comment(1)
@GateKiller: Note that if you use IIS Virtual Directories in your website, your solution can fail because the Application physical path can be different from the file's physical path.Contraption
F
38

Wouldn't it be nice to have Server.RelativePath(path)?

well, you just need to extend it ;-)

public static class ExtensionMethods
{
    public static string RelativePath(this HttpServerUtility srv, string path, HttpRequest context)
    {
        return path.Replace(context.ServerVariables["APPL_PHYSICAL_PATH"], "~/").Replace(@"\", "/");
    }
}

With this you can simply call

Server.RelativePath(path, Request);
Flynt answered 7/3, 2011 at 17:27 Comment(1)
a better replacement for the physical path would be ~/. path.Replace(context.ServerVariables("APPL_PHYSICAL_PATH"), "~/")Fret
D
13

I know this is old but I needed to account for virtual directories (per @Costo's comment). This seems to help:

static string RelativeFromAbsolutePath(string path)
{
    if(HttpContext.Current != null)
    {
        var request = HttpContext.Current.Request;
        var applicationPath = request.PhysicalApplicationPath;
        var virtualDir = request.ApplicationPath;
        virtualDir = virtualDir == "/" ? virtualDir : (virtualDir + "/");
        return path.Replace(applicationPath, virtualDir).Replace(@"\", "/");
    }

    throw new InvalidOperationException("We can only map an absolute back to a relative path if an HttpContext is available.");
}
Dupree answered 5/5, 2012 at 14:5 Comment(0)
U
5

I like the idea from Canoas. Unfortunately I had not "HttpContext.Current.Request" available (BundleConfig.cs).

I changed the methode like this:

public static string RelativePath(this HttpServerUtility srv, string path)
{
     return path.Replace(HttpContext.Current.Server.MapPath("~/"), "~/").Replace(@"\", "/");
}
Ultrasonic answered 24/6, 2015 at 8:19 Comment(0)
E
2

If you used Server.MapPath, then you should already have the relative web path. According to the MSDN documentation, this method takes one variable, path, which is the virtual path of the Web server. So if you were able to call the method, you should already have the relative web path immediately accessible.

Electrophone answered 6/8, 2008 at 8:44 Comment(3)
This is not necessarily true - the MapPath call could have been performed by another method and passed into / called from my file checker method, or (in my case) built from a number of different elements, one of which is my resources directory (defined as "~/__Resources"). Obviously directing the user to this path is going to result in unexpected results. This would also be useful to know because sometimes the absolute file path might have been pulled out of the database with no other contextual information.Economic
@tagsk - I don't know about that. By the way that the method is defined, if the string that you input into Server.MapPath is valid and returns a physical server path, then this had to have been a valid virtual path as well, regardless of how you generated it. Regarding use of the tilde (~) at the beginning of a virtual address, see this MSDN article on ASP.NET Web Site Paths: > ASP.NET includes the Web application > root operator (~), which you can use > when specifying a path in server > cElectrophone
Yaakov - Not so. For instance, a function I use takes a root path and returns an IEnumerable<FileInfo> collection recursively. In my web application I can provide this path resolving my relative path to a physical one, but when I get back this recursive list and want to map them back to relative paths in my application I do not have that info.Mencher
E
0

For asp.net core i wrote helper class to get pathes in both directions.

public class FilePathHelper
{
    private readonly IHostingEnvironment _env;
    public FilePathHelper(IHostingEnvironment env)
    {
        _env = env;
    }
    public string GetVirtualPath(string physicalPath)
    {
        if (physicalPath == null) throw new ArgumentException("physicalPath is null");
        if (!File.Exists(physicalPath)) throw new FileNotFoundException(physicalPath + " doesn't exists");
        var lastWord = _env.WebRootPath.Split("\\").Last();
        int relativePathIndex = physicalPath.IndexOf(lastWord) + lastWord.Length;
        var relativePath = physicalPath.Substring(relativePathIndex);
        return $"/{ relativePath.TrimStart('\\').Replace('\\', '/')}";
    }
    public string GetPhysicalPath(string relativepath)
    {
        if (relativepath == null) throw new ArgumentException("relativepath is null");
        var fileInfo = _env.WebRootFileProvider.GetFileInfo(relativepath);
        if (fileInfo.Exists) return fileInfo.PhysicalPath;
        else throw new FileNotFoundException("file doesn't exists");
    }

from Controller or service inject FilePathHelper and use:

var physicalPath = _fp.GetPhysicalPath("/img/banners/abro.png");

and versa

var virtualPath = _fp.GetVirtualPath(physicalPath);
Ellisellison answered 19/12, 2018 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.