Если мне удалось найти и проверить существование файла с помощью Server.MapPath, и теперь я хочу отправить пользователя непосредственно в этот файл, какой самый быстрый способ преобразовать этот абсолютный путь обратно в относительный веб-путь?
Возможно, это может сработать:
String RelativePath = AbsolutePath.Replace(Request.ServerVariables["APPL_PHYSICAL_PATH"], String.Empty);
Я использую C #, но может быть адаптирован к VB.
Если вы использовали Server.MapPath, то у вас уже должен быть относительный веб-путь. Согласно документации MSDN , этот метод принимает одну переменную, путь , который является виртуальным путем веб-сервера. Поэтому, если вы смогли вызвать метод, у вас уже должен быть доступный относительный веб-путь.
IEnumerable<FileInfo>
рекурсивно возвращает коллекцию. В моем веб-приложении я могу предоставить этот путь, разрешающий мой относительный путь к физическому, но когда я возвращаюсь к этому рекурсивному списку и хочу сопоставить их с относительными путями в моем приложении, у меня нет этой информации. Не было бы неплохо иметь Server.RelativePath (путь) ?
ну, вам просто нужно расширить его ;-)
public static class ExtensionMethods
{
public static string RelativePath(this HttpServerUtility srv, string path, HttpRequest context)
{
return path.Replace(context.ServerVariables["APPL_PHYSICAL_PATH"], "~/").Replace(@"\", "/");
}
}
С этим вы можете просто позвонить
Server.RelativePath(path, Request);
Я знаю, что это старый, но мне нужно было учитывать виртуальные каталоги (согласно комментарию @ Costo). Это, кажется, помогает:
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.");
}
Мне нравится идея Каноаса. К сожалению, у меня не было «HttpContext.Current.Request» (BundleConfig.cs).
Я изменил метод так:
public static string RelativePath(this HttpServerUtility srv, string path)
{
return path.Replace(HttpContext.Current.Server.MapPath("~/"), "~/").Replace(@"\", "/");
}
Для ядра asp.net я написал вспомогательный класс, чтобы получить пути в обоих направлениях.
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");
}
из контроллера или службы вставьте FilePathHelper и используйте:
var physicalPath = _fp.GetPhysicalPath("/img/banners/abro.png");
и наоборот
var virtualPath = _fp.GetVirtualPath(physicalPath);