Problem
Is there a way to convert a path (e.g. “C:whatever.txt”) to a file URI (e.g. “file:/C:/whatever.txt”) in the.NET Framework?
The System.Uri class does the opposite (from a file URI to an absolute path), but I can’t locate anything for converting from an absolute path to a file URI.
It’s also worth noting that this isn’t an ASP.NET application.
Asked by Tinister
Solution #1
The System is in place. The Uri constructor may parse complete file paths and convert them to URI style paths. As a result, you can just perform the following:
var uri = new System.Uri("c:\\foo");
var converted = uri.AbsoluteUri;
Answered by JaredPar
Solution #2
Nobody seems to understand that none of the System is working. Certain paths containing % signs are handled correctly by uri builders.
new Uri(@"C:\%51.txt").AbsoluteUri;
Instead of “file:/C:/ percent 2551.txt,” you’ll get “file:/C:/Q.txt.”
There is no difference between the values of the deprecated dontEscape parameter, and supplying the UriKind yields the same effect. Using the UriBuilder is also ineffective:
new UriBuilder() { Scheme = Uri.UriSchemeFile, Host = "", Path = @"C:\%51.txt" }.Uri.AbsoluteUri
This also returns “file:/C:/Q.txt.”
As far as I can see, the framework doesn’t provide a means to do this properly.
Replace the backslashes with forward slashes and feed the path to Uri to see if it works. EscapeUriString – that is,
new Uri(Uri.EscapeUriString(filePath.Replace(Path.DirectorySeparatorChar, '/'))).AbsoluteUri
This appears to work at first, but if you give it the path C:a b.txt, it returns file:/C:/a percent 2520b.txt instead of file:/C:/a percent 20b.txt – it seems to decide that some sequences should be decoded while others should not. Now we could just prefix with “file:/,” but this ignores UNC paths like remotesharefoo.txt – what appears to be widely accepted on Windows is to convert them to pseudo-urls of the type file:/remote/share/foo.txt, so we should account for that as well.
The problem with EscapeUriString is that it does not escape the ‘#’ character. At this point, it appears that we have no choice but to create our own approach from the ground up. So here’s what I propose:
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();
}
This purposely leaves + and: unencoded, as this appears to be how Windows handles them. It also only encodes latin1 because Internet Explorer is unable to comprehend unicode characters in encoded file urls.
Answered by poizan42
Solution #3
On Linux, none of the aforementioned solutions work.
Attempting to run new Uri(“/home/foo/README.md”) in.NET Core throws an exception:
Unhandled Exception: System.UriFormatException: Invalid URI: The format of the URI could not be determined.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
...
You must provide some information to the CLR about the type of URL you have.
This works:
Uri fileUri = new Uri(new Uri("file://"), "home/foo/README.md");
…as well as the fileUri string. “file:/home/foo/README.md” is “file:/home/foo/README.md” is “file:/home/foo/README.m
This method is also applicable to Windows.
@”C:UsersfooREADME.md”); new Uri(“file:/”), @”C:UsersfooREADME.md”); new Uri(“file:/”), @”C:UsersfooREADME.md”); new Uri ToString()
…emits “file:///C:/Users/foo/README.md”
Answered by Bob Stine
Solution #4
VB.NET:
Dim URI As New Uri("D:\Development\~AppFolder\Att\1.gif")
Different outputs:
URI.AbsolutePath -> D:/Development/~AppFolder/Att/1.gif
URI.AbsoluteUri -> file:///D:/Development/~AppFolder/Att/1.gif
URI.OriginalString -> D:\Development\~AppFolder\Att\1.gif
URI.ToString -> file:///D:/Development/~AppFolder/Att/1.gif
URI.LocalPath -> D:\Development\~AppFolder\Att\1.gif
One liner:
New Uri("D:\Development\~AppFolder\Att\1.gif").AbsoluteUri
Answered by MrCalvin
Solution #5
You can also do: at least in.NET 4.5+:
var uri = new System.Uri("C:\\foo", UriKind.Absolute);
Answered by Gavin Greenwalt
Post is based on https://stackoverflow.com/questions/1546419/convert-file-path-to-a-file-uri