Kimsenin farkına varmadığı şey, System.Uri
inşaatçıların hiçbirinin belirli yolları, içinde yüzde işaretleri olan doğru şekilde işlememesi.
new Uri(@"C:\%51.txt").AbsoluteUri;
Bu size "file:///C:/Q.txt"
bunun yerine verir "file:///C:/%2551.txt"
.
Kullanımdan kaldırılan dontEscape bağımsız değişkeninin değerleri de herhangi bir fark yaratmaz ve UriKind'in belirtilmesi de aynı sonucu verir. UriBuilder ile denemek de yardımcı olmaz:
new UriBuilder() { Scheme = Uri.UriSchemeFile, Host = "", Path = @"C:\%51.txt" }.Uri.AbsoluteUri
Bu da geri döner "file:///C:/Q.txt"
.
Çerçevenin aslında bunu doğru şekilde yapmanın herhangi bir yolu olmadığını söyleyebildiğim kadarıyla.
Ters eğik çizgileri ileri eğik çizgilerle değiştirerek ve Uri.EscapeUriString
-
new Uri(Uri.EscapeUriString(filePath.Replace(Path.DirectorySeparatorChar, '/'))).AbsoluteUri
Bu başlangıçta işe yarıyor gibi görünüyor, ancak yolu C:\a b.txt
verirseniz, file:///C:/a%2520b.txt
bunun yerine sonuçlanırsınız file:///C:/a%20b.txt
- bir şekilde bazı dizilerin kodunun çözülmesine karar verir, ancak diğerleri değil. Şimdi "file:///"
kendimizle ön ek yapabiliriz , ancak bu UNC yollarını \\remote\share\foo.txt
hesaba katmaz - Windows'da genel olarak kabul edilen şey, onları formun sahte url'lerine dönüştürmektir file://remote/share/foo.txt
, bu yüzden bunu da dikkate almalıyız.
EscapeUriString
'#'
karakterden kaçma problemi de var . Bu noktada, kendi yöntemimizi sıfırdan yapmaktan başka seçeneğimiz yok gibi görünüyor. Yani önerdiğim bu:
public static string FilePathToFileUrl(string filePath)
{
StringBuilder uri = new StringBuilder();
foreach (char v in filePath)
{
if ((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || (v >= '0' && v <= '9') ||
v == '+' || v == '/' || v == ':' || v == '.' || v == '-' || v == '_' || v == '~' ||
v > '\xFF')
{
uri.Append(v);
}
else if (v == Path.DirectorySeparatorChar || v == Path.AltDirectorySeparatorChar)
{
uri.Append('/');
}
else
{
uri.Append(String.Format("%{0:X2}", (int)v));
}
}
if (uri.Length >= 2 && uri[0] == '/' && uri[1] == '/') // UNC path
uri.Insert(0, "file:");
else
uri.Insert(0, "file:///");
return uri.ToString();
}
Bu bilerek + ve: kodlarını, genellikle Windows'taki gibi göründüğü gibi kodlanmamış bırakır. Internet Explorer, kodlanmışlarsa dosya url'lerindeki unicode karakterleri anlayamadığından yalnızca latin1 kodlar.
var path = new Uri("file:///C:/whatever.txt").LocalPath;
buna ihtiyacı olan herkes için Uri'yi tekrar yerel bir dosya yoluna dönüştürür.