Ответ 1
Это достаточно хорошо для меня:
protected string GetPath(string path)
{
if (Path.IsPathRooted(path))
{
return path;
}
return Server.MapPath(path);
}
Возможные виртуальные пути:
/folder1/folder2/image.jpg
~/folder1/folder2/image.jpg
folder1/folder2/image.jpg
Конкретный путь:
C:\folder1\folder2\image.jpg
D:\folder1\folder2\image.jpg
C:/folder1/folder2/image.jpg
C:/folder1\folder2/image.jpg
Как вы проверяете, является ли путь виртуальным или нет таким образом, который не подвержен сбою? Причина, по которой я спрашиваю, заключается в том, что, когда я использую Server.MapPath()
по конкретному пути, он генерирует исключение. Однако то, что я передаю в Server.MapPath()
, может быть любым из приведенных выше примеров, и я не знаю, что это такое до выполнения.
Это достаточно хорошо для меня:
protected string GetPath(string path)
{
if (Path.IsPathRooted(path))
{
return path;
}
return Server.MapPath(path);
}
Будет ли Path.GetFullPath(string path)
соответствовать вашим потребностям? Вы можете использовать этот метод, а затем сравнить, изменился ли путь.
if (path == Path.GetFullPath(path))
{
// This is the full path (no changes)
}
else
{
// This is not the full path i.e. 'virtual' (changes)
}
Справка: http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx
Я бы использовал Reflector, чтобы проверить, что делает Server.MapPath()
и делает это.:)
Альтернативой может быть System.IO.Path.GetPathRoot()
- если она возвращает null
, то это относительный путь. Это немного хак, хотя, поскольку он ничего не знает о веб-путях, поэтому, если он работает, это будет работать по совпадению.
Причина, по которой я спрашиваю, заключается в том, что, когда я использую Server.MapPath() по конкретному пути, он генерирует исключение
Вызывает ли это конкретное исключение для этого типа условия или бросает ли он общий? Если исключение специфично для условия, что входной путь был конкретным, я бы поймал это конкретное исключение в вашем коде. Даже если это общее исключение, я все равно поймаю это исключение, вы не сможете его декодировать, если его выбрали, потому что входной путь был виртуальным, но вы можете хотя бы написать свое собственное сообщение об исключении, включая уведомление о том, что это может быть вызвано по виртуальному пути ввода.
Я считаю, что это решение с наименьшей ошибкой, потому что вы полагаетесь на реализацию Server.MapPath(), чтобы определить условия, при которых он терпит неудачу, вместо того, чтобы пытаться создать избыточную оболочку, пытающуюся сделать то же самое. В будущем функциональность MapPath() может измениться, и она может фактически начать поддерживать виртуальные пути, тогда было бы глупо, что у вас есть код, чтобы фактически предотвратить это использование.
Вы можете использовать следующее регулярное выражение...
^(?:[a-zA-Z]:(?:\\|/)|\\\\)
Если вы хотите, чтобы у вас всегда был сопоставленный путь. Вы можете использовать следующий однострочный...
VB.Net
my_path = If(Regex.IsMatch(my_path, "^(?:[a-zA-Z]:(?:\\|/)|\\\\)"), my_path, Server.MapPath(my_path))
С#
my_path = Regex.IsMatch(my_path, @"^(?:[a-zA-Z]:(?:\\|/)|\\\\)") ? my_path : Server.MapPath(my_path);
Это должно корректно работать с обычными путями дисков "c: \", а также с UNC-путями "\\".
//Path.IsPathRooted( "/folder1/folder2/image.jpg" ); возвращает true
public void Main()
{
var path = @"/folder1/folder2/image.jpg";
//is valid path?
if (!System.IO.Path.GetInvalidPathChars().Any(c => path.Contains(c.ToString())))
{
if (IsAbsolutePhysicalPath(path))
{
// This is the full path
}
else
{
// This is not the full path
}
}
}
private bool IsAbsolutePhysicalPath(string path)
{
if (path == null || path.Length < 3)
return false;
// e.g c:\foo
if (path[1] == ':' && IsDirectorySeparatorChar(path[2]))
return true;
// e.g \\server\share\foo or //server/share/foo
return IsUncSharePath(path);
}
private bool IsDirectorySeparatorChar(char ch)
{
return (ch == '\\' || ch == '/');
}
private bool IsUncSharePath(string path)
{
// e.g \\server\share\foo or //server/share/foo
if (path.Length > 2 && IsDirectorySeparatorChar(path[0]) && IsDirectorySeparatorChar(path[1]))
return true;
return false;
}
Справка: http://referencesource.microsoft.com/#System.Web/Util/UrlPath.cs,5e5cf20a50a858e2