C# Path.Combine 用于 URL(第 2 部分)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18004446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 11:01:17  来源:igfitidea点击:

Path.Combine for URLs (part 2)

c#pathuri

提问by Xcelled

For awhile now, I've been searching for a Path.Combine method that works on URLs. This is similiar to Path.Combine for URLs?with one big difference.

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

I'll illustrate with an example. Say we have a base url: http://example.com/somefolderand a file: foo.txt. Thus, the full path would be: http://example.com/somefolder/foo.txt. Sounds simple, right? Ha.

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

I tried the Uri class: Uri.TryCreate(new Uri("http://example.com/somefolder"), "foo.txt", out x);which resulted in "http://example.com/foo.txt".

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

Then I tried Path: System.IO.Path.Combine("http://example.com/somefolder", "foo.txt");which resulted in "http://example.com/somefolder\foo.txt"... Closer, but still no.

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

For kicks, I then tried: System.IO.Path.Combine("http://example.com/somefolder/", "foo.txt")which resulted in "http://example.com/somefolder/foo.txt".

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

The last one worked, but it's basically doing string concatenation at that point.

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

So I think I have two options:

所以我想我有两个选择:

  • Use Path.Combine and replace all \ with /
  • Use basic string concatenation
  • 使用 Path.Combine 并将所有 \ 替换为 /
  • 使用基本的字符串连接

Am I missing a built in framework method for this?

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

UPDATE:The usage case I have is for downloading a bunch of files. My code looks like this:

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

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

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

I'm miffed at having to use string concat in the Uri constructor, as well having to check if the slash is needed (which I omitted in the code).

我对必须在 Uri 构造函数中使用 string concat 感到恼火,还必须检查是否需要斜线(我在代码中省略了)。

It seems to me that what I'm trying to do would come up a lot, since the Uri class handles a lot of other protocols besides http.

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

采纳答案by Todd Menier

Flurl[disclosure: I'm the author] is a tiny URL builder library that can fill the gap with its Url.Combinemethod:

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"

You can get it via NuGet: Install-Package Flurl.

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

I also wanted to point out that you can dramatically improve the efficiency of your code by downloading the files in parallel. There's a couple ways to do that. If you're on .NET 4.5 or above and can rewrite downloadFileas an async method, then your best option would be to replace your forloop with something like this:

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

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

Otherwise, if you're stuck on .NET 4, you can still achieve parallelism easily by using Parallel.ForEach:

否则,如果您坚持使用 .NET 4,您仍然可以通过使用Parallel.ForEach轻松实现并行性

Parallel.ForEach(filenames, f => downloadFile(Url.Combine(folder, f)));

回答by defong

This is how the Uri class works.

这就是 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");  

Basically do it via string manipulation simplest and do

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

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

If you want to find out more. Check out this post C# Url Builder Class

如果你想了解更多。查看这篇文章C# Url Builder Class

Updated answer

更新答案

When referring to base uri it will always be http://example.com/anything to the right is just path.

当提到基本 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;
    }
}

回答by Denny Jacob

I have a static method for this purpose:

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

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

}

回答by Rex Bloom

Here is a LINQ version of something close to the above answer.

这是接近上述答案的 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

回答by Rex Bloom

Omg, why all of you write such complex code? It is very simple:

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

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

Example of use:

使用示例:

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

Result url is "http://something.com/task/status/dfgd/111/qqq"

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