将文件路径转换为文件URI?

Tin*_*ter 191 .net c# uri path

.NET Framework是否有任何方法将路径(例如"C:\whatever.txt")转换为文件URI(例如"file:///C:/whatever.txt")?

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

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

Jar*_*Par 279

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

var uri = new System.Uri("c:\\foo");
var converted = uri.AbsoluteUri;
Run Code Online (Sandbox Code Playgroud)

  • `var path = new Uri("file:/// C:/whatever.txt").Localocal;`对于任何需要它的人来说,`也将Uri变回本地文件路径. (73认同)
  • 遗憾的是,这不正确.例如`new Uri(@"C:\%51.txt").AbsoluteUri`给你``file:/// C:/Q.txt``而不是``file:/// C:/% 2551.txt"` (5认同)
  • 这不适用于带空格的路径,即:“C:\test folder\whatever.txt” (4认同)
  • 这也不适用于包含 # 字符的路径。 (4认同)
  • 作为一个说明.那些Uri可以在VS输出中单击,R#单元测试在会话窗口输出 (2认同)
  • 在 Uri 构造函数中将 dontEscape 参数设置为 true 使 # 作为锚点对我有用,但文档说构造函数已被弃用。构建 URI 并稍后将锚附加到 AbsoluteUri 可能会更好 (.NET 5) (2认同)

poi*_*n42 34

没有人似乎意识到的是,没有一个System.Uri构造函数正确地处理具有百分号的某些路径.

new Uri(@"C:\%51.txt").AbsoluteUri;
Run Code Online (Sandbox Code Playgroud)

这给你"file:///C:/Q.txt"而不是"file:///C:/%2551.txt".

不推荐使用的dontEscape参数的值都没有任何区别,并且指定UriKind也会产生相同的结果.尝试使用UriBuilder也无济于事:

new UriBuilder() { Scheme = Uri.UriSchemeFile, Host = "", Path = @"C:\%51.txt" }.Uri.AbsoluteUri
Run Code Online (Sandbox Code Playgroud)

"file:///C:/Q.txt"也会返回.

据我所知,框架实际上缺乏正确的方法.

我们可以尝试通过用正斜杠替换反斜杠并将路径提供给Uri.EscapeUriString- 即

new Uri(Uri.EscapeUriString(filePath.Replace(Path.DirectorySeparatorChar, '/'))).AbsoluteUri
Run Code Online (Sandbox Code Playgroud)

这似乎首先起作用,但如果你给它路径C:\a b.txt然后你最终得到file:///C:/a%2520b.txt而不是file:///C:/a%20b.txt- 不知何故它决定一些序列应该被解码而不是其他.现在,我们可以只使用前缀与"file:///"自己,但是这未能采取UNC路径类似\\remote\share\foo.txt考虑-什么似乎在Windows上普遍接受的是把它们变成形式的伪网址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();
}
Run Code Online (Sandbox Code Playgroud)

这故意留下+和:未编码,因为它似乎通常是在Windows上完成的.它也只对latin1进行编码,因为如果编码,Internet Explorer无法理解文件URL中的unicode字符.

  • 您可以根据MIT许可证的条款使用上面的代码(我不相信那些简短的内容甚至应该是受版权保护的,但现在您有明确的授权) (4认同)

MrC*_*vin 8

VB.NET:

Dim URI As New Uri("D:\Development\~AppFolder\Att\1.gif")
Run Code Online (Sandbox Code Playgroud)

不同产出:

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
Run Code Online (Sandbox Code Playgroud)

一个班轮:

New Uri("D:\Development\~AppFolder\Att\1.gif").AbsoluteUri
Run Code Online (Sandbox Code Playgroud)

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

  • `AbsoluteUri`是正确的,因为它也将空格编码为%20. (2认同)

Bob*_*ine 7

上面的解决方案在Linux上不起作用。

使用.NET Core,尝试执行将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)
   ...
Run Code Online (Sandbox Code Playgroud)

您需要给CLR一些有关您拥有哪种URL的提示。

这有效:

Uri fileUri = new Uri(new Uri("file://"), "home/foo/README.md");
Run Code Online (Sandbox Code Playgroud)

...并且返回的字符串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"

  • 如果您知道路径是绝对路径,则可以使用 `new Uri("/path/to/file", UriKind.Absolute);` (2认同)

小智 5

至少在 .NET 4.5+ 中,您还可以执行以下操作:

var uri = new System.Uri("C:\\foo", UriKind.Absolute);
Run Code Online (Sandbox Code Playgroud)

  • 这也不能正常工作,`new Uri(@"C:\%51.txt",UriKind.Absolute).AbsoluteUri` 返回 `"file:///C:/Q.txt"` 而不是 `"file :///C:/%2551.txt"` (3认同)