c# - 适用于URL的Path.Combine?





.net asp.net (25)


We use the following simple helper method to join arbitrary number of URL parts together:

public static string JoinUrlParts(params string[] urlParts)
{
    return string.Join("/", urlParts.Where(up => !string.IsNullOrEmpty(up)).ToList().Select(up => up.Trim('/')).ToArray());
}

Note, that it doesn't support '../../something/page.htm'-style relative URL-s!

Path.Combine非常方便,但是.NET框架中是否有类似的功能?

我正在寻找这样的语法:

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

这将返回:

"http://MyUrl.com/Images/Image.jpg"




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

瑞恩库克的答案接近我所追求的,可能更适合其他开发者。 但是,它将http://添加到字符串的开头,并且通常它会比我之后的格式更多一些。

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

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

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

此代码通过以下测试,这恰好在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



我的通用解决方案

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;
}



更多的建议...我已经综合了以上所有内容:

    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(
            "Http://MyUrl.com/Images/Image.jpg",
            path);
    }



将URL与URI相结合的规则

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

  • 路径(目录)必须以'/'结尾。 如果路径没有以'/'结尾,最后一部分被视为一个文件名,并且在试图与下一个url部分结合时会被连接起来。
  • 有一个例外:基地址地址(无目录信息)不需要以'/'结尾
  • 路径部分不能以'/'开头,如果以'/'开头,则每个存在的来自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();
        });



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

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

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




这两个工作

  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 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");



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

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]);
        }
    }
}



    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一样的好处




我知道这已经得到解答,但将它们合并并确保它始终正确的一种简单方法是..

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



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

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



这个怎么样?

 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);
        }
    }



There is a Todd Menier's comment above that Flurl includes a Url.Combine.

更多细节:

Url.Combine is basically a Path.Combine for URLs, ensuring one and only one separator character between parts:

var url = Url.Combine(
    "http://foo.com/",
    "/too/", "/many/", "/slashes/",
    "too", "few?",
    "x=1", "y=2"
// result: "http://www.foo.com/too/many/slashes/too/few?x=1&y=2" 



这是我的方法,我也会为自己使用它

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);
}



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

这是一个例子:

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



这里已经有了一些很好的答案。 基于mdsharpe建议,下面是一个扩展方法,可以在处理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




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

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

注意:因为存在系统类System.Security.Policy.Url ,所以可以更改类名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



例如瑞安,以链接到该函数结束。 做得好。

一个建议Brian:如果你将这些代码封装在一个函数中,你可能希望在TryCreate调用之前使用UriBuilder来封装基本URL。

否则,基本URL必须包含该方案(其中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");
}



以下是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);
    }

来源: UrlUtility.Combine




I have to point out that Path.Combine appears to work for this also directly atleast on .NET4







一个简单的衬垫:

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

受@Matt Sharpe的回答启发。




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



在Git Bash中,输入命令:

git remote set-url origin https://NewRepoLink.git

输入凭据

完成





c# .net asp.net url path