Path.Combine的url?

Path.Combine很方便,但在.NET框架中有没有类似的function?

我正在寻找这样的语法:

Url.Combine("http://MyUrl.com/", "/Images/Image.jpg") 

这将返回:

"Images/Image.jpg"

Uri有一个构造函数,应该为你做这个: new Uri(Uri baseUri, string relativeUri)

这是一个例子:

 Uri baseUri = new Uri("http://www.contoso.com"); Uri myUri = new Uri(baseUri, "catalog/shownew.htm"); 

您使用Uri.TryCreate( ... )

 Uri result = null; if (Uri.TryCreate(new Uri("http://msdn.microsoft.com/en-us/library/"), "/en-us/library/system.uri.trycreate.aspx", out result)) { Console.WriteLine(result); } 

将返回:

http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx

这可能是一个适当简单的解决scheme:

 public static string Combine(string uri1, string uri2) { uri1 = uri1.TrimEnd('/'); uri2 = uri2.TrimStart('/'); return string.Format("{0}/{1}", uri1, uri2); } 

这里已经有一些很好的答案。 基于mdsharpe的build议,这里有一个扩展方法,当你想处理Uri实例时可以很容易地使用:

 using System; using System.Linq; public static class UriExtensions { public static Uri Append(this Uri uri, params string[] paths) { return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => string.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/')))); } } 

和用法示例:

 var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri; 

这将产生http://example.com/subpath/part1/part2

这个问题得到了一些伟大的,高度投票的答案!

Ryan Cook的答案与我之后的答案很接近,可能更适合于其他开发者。 但是,它将http://添加到string的开头,一般来说,它的格式要比我以前多一些。

另外,对于我的用例来说,解决相对path并不重要。

mdsharp的答案也包含了一个好主意的种子,尽pipe实际的实现需要更多的细节来完成。 这是一个试图充实(我正在使用这个在生产中):

C#

 public string UrlCombine(string url1, string url2) { if (url1.Length == 0) { return url2; } if (url2.Length == 0) { return url1; } url1 = url1.TrimEnd('/', '\\'); url2 = url2.TrimStart('/', '\\'); return string.Format("{0}/{1}", url1, url2); } 

VB.Net

 Public Function UrlCombine(ByVal url1 As String, ByVal url2 As String) As String If url1.Length = 0 Then Return url2 End If If url2.Length = 0 Then Return url1 End If url1 = url1.TrimEnd("/"c, "\"c) url2 = url2.TrimStart("/"c, "\"c) Return String.Format("{0}/{1}", url1, url2) End Function 

这段代码通过了下面的testing,这恰好在VB中:

 <TestMethod()> Public Sub UrlCombineTest() Dim target As StringHelpers = New StringHelpers() Assert.IsTrue(target.UrlCombine("test1", "test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1/", "test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1", "/test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1/", "/test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("/test1/", "/test2/") = "/test1/test2/") Assert.IsTrue(target.UrlCombine("", "/test2/") = "/test2/") Assert.IsTrue(target.UrlCombine("/test1/", "") = "/test1/") End Sub 

根据您提供的示例url ,我将假设您想要合并与您的网站相关的url。

基于这个假设,我将提出这个解决scheme作为对你的问题的最恰当的回应:“Path.Combine是方便的,在URL的框架中是否有类似的function

由于那里在URL的框架中有一个类似的function ,我build议正确的是:“VirtualPathUtility.Combine”方法。 以下是MSDN参考链接: VirtualPathUtility.Combine方法

有一个警告:我相信这只适用于网站相对于您的网站(也就是说,你不能用它来产生链接到另一个网站。例如, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets"); )。

Path.Combine不适合我,因为可以有像“|” 在QueryString参数,因此Url,这将导致一个ArgumentException。

我首先尝试了新的Uri(Uri baseUri,string relativeUri)方法,由于Uri的原因,我失败了,如http://www.mediawiki.org/wiki/Special:SpecialPages

 new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages") 

将会导致Special:SpecialPages,因为Special之后的冒号表示scheme。

所以我最终不得不采取mdsharpe / Brian MacKays的路线,并进一步开发了多个uri部分:

 public static string CombineUri(params string[] uriParts) { string uri = string.Empty; if (uriParts != null && uriParts.Count() > 0) { char[] trims = new char[] { '\\', '/' }; uri = (uriParts[0] ?? string.Empty).TrimEnd(trims); for (int i = 1; i < uriParts.Count(); i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; } 

用法: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")

 Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/") 

我只是把小的扩展方法放在一起

 public static string UriCombine (this string val, string append) { if (String.IsNullOrEmpty(val)) return append; if (String.IsNullOrEmpty(append)) return val; return val.TrimEnd('/') + "/" + append.TrimStart('/'); } 

可以这样使用:

 "www.example.com/".UriCombine("/images").UriCombine("first.jpeg"); 

举个例子,瑞安,结束与该function的链接。 做得好。

一个build议Brian:如果你把这个代码包装在一个函数中,你可能想要在TryCreate调用之前使用UriBuilder来包装基本的URL。

否则,基本URL必须包含该scheme(其中UriBuilder将采用http://)。 只是一个想法:

 public string CombineUrl(string baseUrl, string relativeUrl) { UriBuilder baseUri = new UriBuilder(baseUrl); Uri newUri; if (Uri.TryCreate(baseUri.Uri, relativeUrl, out newUri)) return newUri.ToString(); else throw new ArgumentException("Unable to combine specified url values"); } 

结合Url的多个部分可能有点棘手。 您可以使用2参数构造函数Uri(baseUri, relativeUri) ,也可以使用Uri.TryCreate()实用程序函数。 无论是哪种情况,您最终都会返回不正确的结果,因为这些方法会继续截断第一个参数baseUri的相关部分,即从http://google.com/some/thinghttp://google.com

为了能够将多个部分组合成最终的url,可以复制下面的两个函数:

  public static string Combine(params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; var urlBuilder = new StringBuilder(); foreach (var part in parts) { var tempUrl = tryCreateRelativeOrAbsolute(part); urlBuilder.Append(tempUrl); } return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToString()); } private static string tryCreateRelativeOrAbsolute(string s) { System.Uri uri; System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri); string tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToString()); return tempUrl; } 

用unit testing来演示使用的完整代码可以在https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.csfind。;

我有unit testing涵盖3个最常见的情况: 在这里输入图像描述

我知道这已被回答,但一个简单的方法来结合他们,并确保它总是正确的是..

 string.Format("{0}/{1}", Url1.Trim('/'), Url2); 

这个答案可能会在上面的所有答案中都丢失,但是我发现UriBuilder对于这样的事情非常有效。

 UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath); Uri url = urlb.Uri; return url.AbsoluteUri; 

有关更多构造函数和文档,请参阅UriBuilder类 – MSDN 。

以下是Microsoft的(OfficeDev PnP)方法UrlUtility.Combine :

  const char PATH_DELIMITER = '/'; /// <summary> /// Combines a path and a relative path. /// </summary> /// <param name="path"></param> /// <param name="relative"></param> /// <returns></returns> public static string Combine(string path, string relative) { if(relative == null) relative = String.Empty; if(path == null) path = String.Empty; if(relative.Length == 0 && path.Length == 0) return String.Empty; if(relative.Length == 0) return path; if(path.Length == 0) return relative; path = path.Replace('\\', PATH_DELIMITER); relative = relative.Replace('\\', PATH_DELIMITER); return path.TrimEnd(PATH_DELIMITER) + PATH_DELIMITER + relative.TrimStart(PATH_DELIMITER); } 

来源: GitHub

我的通用解决scheme

 public static string Combine(params string[] uriParts) { string uri = string.Empty; if (uriParts != null && uriParts.Any()) { char[] trims = new char[] { '\\', '/' }; uri = (uriParts[0] ?? string.Empty).TrimEnd(trims); for (int i = 1; i < uriParts.Length; i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; } 

我知道我晚了,但我创造了这个function,这将使您的生活更轻松

  /// <summary> /// the ultimate Path combiner of all time /// </summary> /// <param name="IsURL"> /// true - if the paths are internet urls,false - if the paths are local urls,this is very important as this will be used to decide which separator will be used /// </param> /// <param name="IsRelative">just adds the separator at the beginning</param> /// <param name="IsFixInternal">fix the paths from within (by removing duplicate separators and correcting the separators)</param> /// <param name="parts">the paths to combine</param> /// <returns>the combined path</returns> public static string PathCombine(bool IsURL , bool IsRelative , bool IsFixInternal , params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; char separator = IsURL ? '/' : '\\'; if (parts.Length == 1 && IsFixInternal) { string validsingle; if (IsURL) { validsingle = parts[0].Replace('\\' , '/'); } else { validsingle = parts[0].Replace('/' , '\\'); } validsingle = validsingle.Trim(separator); return (IsRelative ? separator.ToString() : string.Empty) + validsingle; } string final = parts .Aggregate ( (string first , string second) => { string validfirst; string validsecond; if (IsURL) { validfirst = first.Replace('\\' , '/'); validsecond = second.Replace('\\' , '/'); } else { validfirst = first.Replace('/' , '\\'); validsecond = second.Replace('/' , '\\'); } var prefix = string.Empty; if (IsFixInternal) { if (IsURL) { if (validfirst.Contains("://")) { var tofix = validfirst.Substring(validfirst.IndexOf("://") + 3); prefix = validfirst.Replace(tofix , string.Empty).TrimStart(separator); var tofixlist = tofix.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = separator + string.Join(separator.ToString() , tofixlist); } else { var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = string.Join(separator.ToString() , firstlist); } var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validsecond = string.Join(separator.ToString() , secondlist); } else { var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = string.Join(separator.ToString() , firstlist); validsecond = string.Join(separator.ToString() , secondlist); } } return prefix + validfirst.Trim(separator) + separator + validsecond.Trim(separator); } ); return (IsRelative ? separator.ToString() : string.Empty) + final; } 

它适用于URL和普通path

用法:

  //fixes internal paths Console.WriteLine(PathCombine(true , true , true , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : /folder 1/folder2/folder3/somefile.ext //doesn't fix internal paths Console.WriteLine(PathCombine(true , true , false , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : /folder 1//////////folder2////folder3/somefile.ext //don't worry about url prefixes when fixing internal paths Console.WriteLine(PathCombine(true , false , true , @"/\/\/https:/\/\/\lul.com\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : https://lul.com/folder2/folder3/somefile.ext Console.WriteLine(PathCombine(false , true , true , @"../../../\\..\...\./../somepath" , @"anotherpath")); //result : \..\..\..\..\...\.\..\somepath\anotherpath 

我知道这个问题很好的回答,但是我觉得这个有用,因为它具有以下特点

  • 抛出空或空白
  • 更接近模拟System.Io.Path静态类
  • 为多个Url段获取params参数

注意:类名Url可以改变,因为有一个系统类System.Security.Policy.Url

 public static class Url { private static string InternalCombine(string source, string dest) { // If the source is null or white space retune the dest only if (string.IsNullOrWhiteSpace(source)) { throw new ArgumentException("Cannot be null or white space", "source"); // throw new ArgumentException("Cannot be null or white space", nameof(source)); // c# 6.0 Nameof Expression } if (string.IsNullOrWhiteSpace(dest)) { throw new ArgumentException("Cannot be null or white space", "dest"); // throw new ArgumentException("Cannot be null or white space", nameof(dest)); // c# 6.0 Nameof Expression } source = source.TrimEnd('/', '\\'); dest = dest.TrimStart('/', '\\'); return string.Format("{0}/{1}", source, dest); // return $"{source}/{dest}"; // c# 6.0 string interpolation } public static string Combine(string source, params string[] args) { return args.Aggregate(source, InternalCombine); } } 

结果

 Url.Combine("test1", "test2"); Url.Combine("test1//", "test2"); Url.Combine("test1", "/test2"); // Result = test1/test2 Url.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ; // Result = test1/test2/test3 Url.Combine("/test1/", "/test2/", null); Url.Combine("", "/test2/"); Url.Combine("/test1/", null); // Throws an ArgumentException 

这个怎么样?

  public static class WebPath { public static string Combine(params string[] args) { var prefixAdjusted = args.Select(x => x.StartsWith("/") && !x.StartsWith("http") ? x.Substring(1) : x); return string.Join("/", prefixAdjusted); } } 

这是我的方法,我也将使用它

 public static string UrlCombine(string part1, string part2) { string newPart1 = string.Empty; string newPart2 = string.Empty; string seprator = "/"; // if either part1 or part 2 is empty, // we don't need to combine with seprator if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2)) { seprator = string.Empty; } // if part1 is not empty // remove '/' at last if (!string.IsNullOrEmpty(part1)) { newPart1 = part1.TrimEnd('/'); } // if part2 is not empty // remove '/' at first if (!string.IsNullOrEmpty(part2)) { newPart2 = part2.TrimStart('/'); } // now finally combine return string.Format("{0}{1}{2}", newPart1, seprator, newPart2); } 
  private Uri UriCombine(string path1, string path2, string path3 = "", string path4 = "") { string path = System.IO.Path.Combine(path1, path2.TrimStart('\\', '/'), path3.TrimStart('\\', '/'), path4.TrimStart('\\', '/')); string url = path.Replace('\\','/'); return new Uri(url); } 

具有完全像Path.Combine一样的好处

更多的build议…我已经综合了以上所有:

  public static string UrlPathCombine(string path1, string path2) { path1 = path1.TrimEnd('/') + "/"; path2 = path2.TrimStart('/'); return Path.Combine(path1, path2) .Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } [TestMethod] public void TestUrl() { const string P1 = "http://msdn.microsoft.com/slash/library//"; Assert.AreEqual("http://msdn.microsoft.com/slash/library/site.aspx", UrlPathCombine(P1, "//site.aspx")); var path = UrlPathCombine("Http://MyUrl.com/", "Images/Image.jpg"); Assert.AreEqual( "Images/Image.jpg", path); } 

那么,我只是连接两个string,并使用正则expression式来执行清理部分。

  public class UriTool { public static Uri Join(string path1, string path2) { string url = path1 + "/" + path2; url = Regex.Replace(url, "(?<!http:)/{2,}", "/"); return new Uri(url); } } 

所以,你可以这样使用:

  string path1 = "http://someaddress.com/something/"; string path2 = "/another/address.html"; Uri joinedUri = UriTool.Join(path1, path2); // joinedUri.ToString() returns "http://someaddress.com/something/another/address.html" 

希望对某人有用!

我用这个代码来解决这个问题:

 string[] brokenBaseUrl = Context.Url.TrimEnd('/').Split('/'); string[] brokenRootFolderPath = RootFolderPath.Split('/'); for (int x = 0; x < brokenRootFolderPath.Length; x++) { //if url doesn't already contain member, append it to the end of the string with / in front if (!brokenBaseUrl.Contains(brokenRootFolderPath[x])) { if (x == 0) { RootLocationUrl = Context.Url.TrimEnd('/'); } else { RootLocationUrl += String.Format("/{0}", brokenRootFolderPath[x]); } } } 

将URL与URI结合起来的规则

为了避免奇怪的行为,有一条规则可以遵循:

  • path(目录)必须以'/'结尾。 如果path没有以“/”结尾,最后一个部分就像文件名一样对待,当试图与下一个url部分结合时,它会被连接在一起。
  • 有一个例外:基地址(无目录信息)不需要以'/'结尾
  • path部分不能以'/'开始,如果以'/'开始,则每个存在的来自URL的相关信息都会被删除…添加string。空的部分path也会从URL中删除相对目录!

如果您遵循上述规则,则可以将URL与下面的代码组合在一起。 根据你的情况,你可以添加多个“目录”部分到url…

  var pathParts = new string[] { destinationBaseUrl, destinationFolderUrl, fileName }; var destination = pathParts.Aggregate((left, right) => { if (string.IsNullOrWhiteSpace(right)) return left; return new Uri(new Uri(left), right).ToString(); }); 

这两个工作

  Uri final = new Uri(Regex.Replace(baseUrl + "/" + relativePath, "(?<!http:)/{2,}", "/")); 

要么

  Uri final =new Uri(string.Format("{0}/{1}", baseUrl.ToString().TrimEnd('/'), relativePath.ToString().TrimStart('/'))); 

如果

baseUrl =“ http://tesrurl.test.com/Int18

relativePath =“To_Folder”

输出= http://tesrurl.test.com/Int18/To_Folder

下面的代码会出现一些错误

  // if you use below code, some issues will be there in final uri Uri final= new Uri(baseUrl ,relativePath ); 

一个简单的衬垫:

 public static string Combine(this string uri1, string uri2) => $"{uri1.TrimEnd('/')}/{uri2.TrimStart('/')}"; 

受@Matt Sharpe的回答启发。

我必须指出,Path.Combine似乎也适用于.NET4

我还没有使用下面的代码,但在我的互联网旅行中发现它解决了一个URL组合问题 – 希望它是一个简洁(和成功!)的答案:

 VirtualPathUtility.Combine