Czy .NET Framework ma jakieś metody konwersji ścieżki (np. "C:\whatever.txt"
) Na identyfikator URI pliku (np. "file:///C:/whatever.txt"
)?
System.Uri klasa ma odwróconych (z pliku URI do ścieżki bezwzględnej), ale nie tak daleko, jak mogę znaleźć do konwersji do pliku URI.
Ponadto nie jest to aplikacja ASP.NET.
var path = new Uri("file:///C:/whatever.txt").LocalPath;
zamienia Uri z powrotem w lokalną ścieżkę plików dla każdego, kto tego potrzebuje.new Uri(@"C:\%51.txt").AbsoluteUri
daje"file:///C:/Q.txt"
zamiast"file:///C:/%2551.txt"
Nikt nie zdaje sobie sprawy z tego, że żaden z
System.Uri
konstruktorów nie obsługuje poprawnie niektórych ścieżek ze znakami procentowymi.To daje
"file:///C:/Q.txt"
zamiast"file:///C:/%2551.txt"
.Żadna z wartości przestarzałego argumentu dontEscape nie robi żadnej różnicy, a określenie UriKind daje również ten sam wynik. Próbowanie z UriBuilder nie pomaga:
To również powraca
"file:///C:/Q.txt"
.O ile mogę stwierdzić, frameworkowi brakuje właściwie żadnego sposobu, aby to zrobić poprawnie.
Możemy tego spróbować, zastępując ukośniki odwrotne ukośnikami i kierując ścieżkę do
Uri.EscapeUriString
- tjZ początku wydaje się, że to działa, ale jeśli podasz ścieżkę,
C:\a b.txt
tofile:///C:/a%2520b.txt
zamiast tegofile:///C:/a%20b.txt
- w jakiś sposób decyduje, że niektóre sekwencje powinny zostać zdekodowane, a inne nie. Teraz możemy po prostu przedrostek ze"file:///"
sobą, jednak nie bierze to\\remote\share\foo.txt
pod uwagę ścieżek UNC, jak się wydaje - ogólnie wydaje się, że w systemie Windows powszechnie przyjmuje się przekształcanie ich w pseudo-adresy URL formularzafile://remote/share/foo.txt
, dlatego też powinniśmy to wziąć pod uwagę.EscapeUriString
ma również problem polegający na tym, że nie ucieka'#'
postaci. Wydaje się w tym momencie, że nie mamy innego wyjścia, jak stworzyć własną metodę od zera. Oto co sugeruję:To celowo pozostawia + i: niezakodowane, ponieważ wydaje się, że tak zwykle dzieje się w systemie Windows. Koduje także Latin1, ponieważ Internet Explorer nie może zrozumieć znaków Unicode w adresach URL plików, jeśli są one zakodowane.
źródło
Powyższe rozwiązania nie działają w systemie Linux.
Przy użyciu .NET Core próba wykonania
new Uri("/home/foo/README.md")
powoduje wyjątek:Musisz dać CLR kilka wskazówek na temat tego, jaki masz adres URL.
To działa:
... a ciąg zwracany przez
fileUri.ToString()
to"file:///home/foo/README.md"
Działa to również w systemie Windows.
new Uri(new Uri("file://"), @"C:\Users\foo\README.md").ToString()
... emituje
"file:///C:/Users/foo/README.md"
źródło
new Uri("/path/to/file", UriKind.Absolute);
VB.NET:
Różne wyjścia:
Jedna wkładka:
źródło
AbsoluteUri
jest poprawny, ponieważ koduje również spacje do% 20.Przynajmniej w .NET 4.5+ możesz także:
źródło
UriFormatException
jednego dnia?new Uri(@"C:\%51.txt",UriKind.Absolute).AbsoluteUri
zwraca"file:///C:/Q.txt"
zamiast"file:///C:/%2551.txt"
UrlCreateFromPath na ratunek! Cóż, nie do końca, ponieważ nie obsługuje formatów rozszerzonych i ścieżek UNC, ale nie jest to trudne do pokonania:
W przypadku, gdy ścieżka zaczyna się od specjalnego prefiksu, zostaje usunięta. Chociaż dokumentacja nie wspomina o tym, funkcja podaje długość adresu URL, nawet jeśli bufor jest mniejszy, więc najpierw uzyskuję długość, a następnie przydzielam bufor.
Kilka bardzo interesujących spostrzeżeń, jakie miałem, to że „\\ urządzenie \ ścieżka” jest poprawnie przekształcana na „plik: // urządzenie / ścieżka”, a konkretnie „\\ localhost \ ścieżka” jest przekształcana na „plik: /// ścieżka” .
Funkcja WinApi zdołała zakodować znaki specjalne, ale pozostawia znaki specyficzne dla Unicode niezakodowane, w przeciwieństwie do konstruktora Uri . W takim przypadku AbsoluteUri zawiera poprawnie zakodowany adres URL, a OriginalString może być używany do zachowania znaków Unicode.
źródło
Obejście jest proste. Wystarczy użyć metody Uri (). ToString () i później kodować białe spacje, jeśli takie istnieją.
poprawnie zwraca plik: /// C: / my% 20example ㄓ .txt
źródło