转换为文件URI文件路径?(Convert file path to a file URI?)

2019-07-21 19:50发布

是否在.NET Framework有转换路径的任何方法(如"C:\whatever.txt"到一个文件URI(如"file:///C:/whatever.txt"

该的System.Uri类有反向(从文件URI以绝对路径),但没有就我可以找到转换为文件URI。

此外,这是不是一个ASP.NET应用程序。

Answer 1:

System.Uri构造函数来解析完整的文件路径,并把它们变成URI风格的路径的能力。 所以,你可以做到以下几点:

var uri = new System.Uri("c:\\foo");
var converted = uri.AbsoluteUri;


Answer 2:

没有什么人似乎意识到的是,没有任何的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无法理解文件URL Unicode字符。



Answer 3:

VB.NET:

Dim URI As New Uri("D:\Development\~AppFolder\Att\1.gif")

不同的输出:

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

一个内胆:

New Uri("D:\Development\~AppFolder\Att\1.gif").AbsoluteUri

输出file:///D:/Development/~AppFolder/Att/1.gif



Answer 4:

该解决方案上面的不工作在Linux上。

使用.NET的核心,试图执行new Uri("/home/foo/README.md")导致异常:

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)
   ...

你需要给CLR你有什么样的URL的一些提示。

这工作:

Uri fileUri = new Uri(new Uri("file://"), "home/foo/README.md");

...和返回的字符串fileUri.ToString()"file:///home/foo/README.md"

这适用于Windows,太。

new Uri(new Uri("file://"), @"C:\Users\foo\README.md").ToString()

...发出"file:///C:/Users/foo/README.md"



Answer 5:

至少在.NET 4.5 +你也可以这样做:

var uri = new System.Uri("C:\\foo", UriKind.Absolute);


Answer 6:

UrlCreateFromPath来救援! 好了,不完全的,因为它不支持扩展和UNC路径格式,但事实并非如此难以克服:

public static Uri FileUrlFromPath(string path)
{
    const string prefix = @"\\";
    const string extended = @"\\?\";
    const string extendedUnc = @"\\?\UNC\";
    const string device = @"\\.\";
    const StringComparison comp = StringComparison.Ordinal;

    if(path.StartsWith(extendedUnc, comp))
    {
        path = prefix+path.Substring(extendedUnc.Length);
    }else if(path.StartsWith(extended, comp))
    {
        path = prefix+path.Substring(extended.Length);
    }else if(path.StartsWith(device, comp))
    {
        path = prefix+path.Substring(device.Length);
    }

    int len = 1;
    var buffer = new StringBuilder(len);
    int result = UrlCreateFromPath(path, buffer, ref len, 0);
    if(len == 1) Marshal.ThrowExceptionForHR(result);

    buffer.EnsureCapacity(len);
    result = UrlCreateFromPath(path, buffer, ref len, 0);
    if(result == 1) throw new ArgumentException("Argument is not a valid path.", "path");
    Marshal.ThrowExceptionForHR(result);
    return new Uri(buffer.ToString());
}

[DllImport("shlwapi.dll", CharSet=CharSet.Auto, SetLastError=true)]
static extern int UrlCreateFromPath(string path, StringBuilder url, ref int urlLength, int reserved);

如果路径以一个特殊的前缀开头,它就会被删除。 虽然文档没有提到它时,函数输出即使缓冲区是较小的URL的长度,所以我首先获得的长度,然后分配缓冲区。

一些非常有趣的观察我的是,虽然“\\设备\路径”是否正确转化为“文件://设备/路径”,特别是“\\本地主机\路径”被转换只是“文件:///路径” 。

该WINAPI功能管理,以特殊字符进行编码,但留下Unicode的特定字符未编码的,不像乌里 construtor。 在这种情况下, 绝对URI包含了编码正确的URL,而OriginalString可以用来保留Unicode字符。



Answer 7:

解决方法很简单。 只需使用URI()。ToString()方法和百分比编码的空格,如果有的话,算账。

string path = new Uri("C:\my exampleㄓ.txt").ToString().Replace(" ", "%20");

正确返回文件:/// C:/我的%20example ㄓ .TXT



文章来源: Convert file path to a file URI?
标签: c# .net path uri