21

一段时间以来,我一直在寻找适用于 URL 的 Path.Combine 方法。这类似于 URL 的 Path.Combine 吗?有一个很大的不同。

我将举例说明。假设我们有一个基本 url:http://example.com/somefolder和一个 file: foo.txt。因此,完整路径将是:http://example.com/somefolder/foo.txt. 听起来很简单,对吧?哈。

我尝试了 Uri 类:Uri.TryCreate(new Uri("http://example.com/somefolder"), "foo.txt", out x);导致"http://example.com/foo.txt".

然后我尝试了 Path:System.IO.Path.Combine("http://example.com/somefolder", "foo.txt");导致"http://example.com/somefolder\foo.txt"... Closer,但仍然没有。

为了踢球,我然后尝试:System.IO.Path.Combine("http://example.com/somefolder/", "foo.txt")导致"http://example.com/somefolder/foo.txt".

最后一个工作,但它基本上是在那个时候进行字符串连接。

所以我想我有两个选择:

  • 使用 Path.Combine 并将所有 \ 替换为 /
  • 使用基本字符串连接

我是否缺少为此的内置框架方法?

更新:我的用例是下载一堆文件。我的代码如下所示:

    public void Download()
    {
        var folder = "http://example.com/somefolder";
        var filenames = getFileNames(folder);

        foreach (var name in filenames)
        {
            downloadFile(new Uri(folder + "/" + name));
        }
    }

我对必须在 Uri 构造函数中使用字符串 concat 以及必须检查是否需要斜杠(我在代码中省略)感到恼火。

在我看来,我正在尝试做的事情会出现很多,因为 Uri 类处理除了 http 之外的许多其他协议。

4

5 回答 5

18

Flurl [披露:我是作者] 是一个微型 URL 构建器库,可以用它的Url.Combine方法填补空白:

string url = Url.Combine("http://www.foo.com/", "/too/", "/many/", "/slashes/", "too", "few");
// result: "http://www.foo.com/too/many/slashes/too/few"

您可以通过 NuGet: 获取它Install-Package Flurl

我还想指出,您可以通过并行下载文件来显着提高代码效率。有几种方法可以做到这一点。如果您使用的是 .NET 4.5 或更高版本并且可以重写downloadFile为异步方法,那么您最好的选择是将for循环替换为以下内容:

var tasks = filenames.Select(f => downloadFileAsync(Url.Combine(folder, f)));
await Task.WhenAll(tasks);

否则,如果您被困在 .NET 4 上,您仍然可以使用Parallel.ForEach轻松实现并行性:

Parallel.ForEach(filenames, f => downloadFile(Url.Combine(folder, f)));
于 2014-03-24T14:43:53.243 回答
9

这就是 Uri 类的工作方式。

var otherUri = new Uri("http://example.com/somefolder"));
// somefolder is just a path
var somefolder = otherUri.GetComponents(UriComponents.PathAndQuery, UriFormat.UriEscaped);

// example one
var baseUri = new Uri("http://example.com/");   
var relativeUri = new Uri("somefolder/file.txt",UriKind.Relative);
var fullUri = new Uri(baseUri, relativeUri);

// example two
var baseUri = new Uri("http://example.com/somefolder"); 
var relativeUri = new Uri("somefolder/file.txt",UriKind.Relative);
var fullUri = new Uri(baseUri, relativeUri);

// example three
var baseUri = new Uri("http://example.com/");   
var fullUri = new Uri(baseUri, "somefolder/file.txt");  

基本上通过最简单的字符串操作来完成

var isValid = Uri.TryCreate(..., out myUri);

如果您想了解更多信息。查看这篇文章C# Url Builder 类

更新的答案

当引用基本 uri 时,它总是http://example.com/右边的任何东西都是路径。

void Main()
{
    var ub = new UriBuilder("http://example.com/somefolder");
    ub.AddPath("file.txt"); 
            var fullUri = ub.Uri;
}
public static class MyExtensions
{
    public static UriBuilder AddPath(this UriBuilder builder, string pathValue)
    {
    var path = builder.Path;

    if (path.EndsWith("/") == false)
    {
        path = path + "/";
    }

    path += Uri.EscapeDataString(pathValue);

    builder.Path = path;
    }
}
于 2013-08-01T22:17:56.557 回答
2

这是接近上述答案的 LINQ 版本。

public static string UrlCombine( this string root, params string[] parts)
{
    return parts
        .Select(part => part.Trim().TrimEnd('/').TrimStart('/').Trim())
        .Aggregate(root, (current, path) => current + ("/" + path));
}

var x = "http://domain.com";

var p = "path";

var u = x.UrlCombine(p, "test.html"); // http://domain.com/path/test.html
于 2016-07-01T19:10:44.553 回答
2

为此,我有一个静态方法:

// Combines urls like System.IO.Path.Combine
// Usage: this.Literal1.Text = CommonCode.UrlCombine("http://stackoverflow.com/", "/questions ", " 372865", "path-combine-for-urls");
public static string UrlCombine(params string[] urls) {
    string retVal = string.Empty;
    foreach (string url in urls)
    {
        var path = url.Trim().TrimEnd('/').TrimStart('/').Trim();
        retVal = string.IsNullOrWhiteSpace(retVal) ? path : new System.Uri(new System.Uri(retVal + "/"), path).ToString();
    }
    return retVal;

}
于 2016-05-19T02:54:34.330 回答
-1

天哪,你们为什么要写这么复杂的代码?这很简单:

private string CombineUrl(params string[] urls)
{
    string result = "";

    foreach (var url in urls)
    {
        if (result.Length > 0 && url.Length > 0)
            result += '/';

        result += url.Trim('/');
    }

    return result;
}

使用示例:

var methodUrl = CombineUrl("http://something.com", "/task/status/", "dfgd/", "/111", "qqq");

结果网址为“ http://something.com/task/status/dfgd/111/qqq

于 2016-12-09T08:41:48.410 回答