สิ่งที่ดูเหมือนจะไม่มีใครรู้คือไม่มีสิ่งSystem.Uri
ก่อสร้างใดถูกต้องจัดการเส้นทางบางอย่างที่มีเครื่องหมายเปอร์เซ็นต์ในพวกเขา
new Uri(@"C:\%51.txt").AbsoluteUri;
นี้จะช่วยให้คุณแทน"file:///C:/Q.txt"
"file:///C:/%2551.txt"
ค่าของอาร์กิวเมนต์ dontEscape ที่คัดค้านไม่ได้สร้างความแตกต่างใด ๆ และการระบุ UriKind ก็ให้ผลลัพธ์เหมือนกันเช่นกัน การลองกับ UriBuilder ไม่ได้ช่วยอะไรทั้ง:
new UriBuilder() { Scheme = Uri.UriSchemeFile, Host = "", Path = @"C:\%51.txt" }.Uri.AbsoluteUri
ผลตอบแทนนี้"file:///C:/Q.txt"
เช่นกัน
เท่าที่ฉันสามารถบอกได้ว่ากรอบงานนั้นขาดวิธีใด ๆ ในการทำสิ่งนี้อย่างถูกต้อง
เราสามารถลองทำได้โดยเปลี่ยนแบ็กสแลชด้วยสแลชไปข้างหน้าและป้อนเส้นทางไปUri.EscapeUriString
- เช่น
new Uri(Uri.EscapeUriString(filePath.Replace(Path.DirectorySeparatorChar, '/'))).AbsoluteUri
สิ่งนี้ดูเหมือนว่าจะใช้งานได้ในตอนแรก แต่ถ้าคุณให้มันเป็นเส้นทางC:\a b.txt
แล้วคุณก็จบลงด้วยการfile:///C:/a%2520b.txt
แทนที่file:///C:/a%20b.txt
- อย่างใดมันจะตัดสินใจว่าบางลำดับควรจะถอดรหัส แต่ไม่ใช่คนอื่น ๆ ตอนนี้เราสามารถนำหน้าด้วย"file:///"
ตัวเราเองได้ แต่สิ่งนี้ล้มเหลวในการนำเส้นทาง UNC \\remote\share\foo.txt
มาพิจารณา - สิ่งที่ดูเหมือนว่าเป็นที่ยอมรับโดยทั่วไปใน Windows คือการเปลี่ยนให้เป็นแบบหลอก URL ของแบบฟอร์มfile://remote/share/foo.txt
ดังนั้นเราจึงควรคำนึงถึงสิ่งนั้นด้วย
EscapeUriString
ยังมีปัญหาว่ามันไม่หนี'#'
ตัวละคร ดูเหมือนว่า ณ จุดนี้เราไม่มีทางเลือกอื่นนอกจากสร้างวิธีการของเราเองตั้งแต่เริ่มต้น ดังนั้นนี่คือสิ่งที่ฉันแนะนำ:
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();
}
สิ่งนี้จงใจปล่อยให้ + และ: ไม่มีการเข้ารหัสเหมือนที่ทำใน Windows นอกจากนี้ยังเข้ารหัสเฉพาะ latin1 เนื่องจาก Internet Explorer ไม่สามารถเข้าใจอักขระ unicode ใน URL ของไฟล์หากมีการเข้ารหัส
var path = new Uri("file:///C:/whatever.txt").LocalPath;
เปลี่ยน Uri กลับไปเป็น filepath ในระบบด้วยสำหรับทุกคนที่ต้องการสิ่งนี้