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.
I'll illustrate with an example. Say we have a base url: http://example.com/somefolder
and a file: foo.txt
. Thus, the full path would be: http://example.com/somefolder/foo.txt
. Sounds simple, right? Ha.
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"
.
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.
For kicks, I then tried: System.IO.Path.Combine("http://example.com/somefolder/", "foo.txt")
which resulted in "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:
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).
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.
Combines two strings into a path. Combine(String, String, String) Combines three strings into a path. Combine(String, String, String, String) Combines four strings into a path.
The file system have the Path. Combine method to combine paths but how to combine a base URL with an absolute or relative URL/URI? var b = CombineUriToString("http://www.my.domain/something/other", "/absolute/path");
Path. Combine uses the Path. PathSeparator and it checks whether the first path has already a separator at the end so it will not duplicate the separators. Additionally, it checks whether the path elements to combine have invalid chars.
Flurl [disclosure: I'm the author] is a tiny URL builder library that can fill the gap with its Url.Combine
method:
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
.
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 downloadFile
as an async method, then your best option would be to replace your for
loop with something like this:
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:
Parallel.ForEach(filenames, f => downloadFile(Url.Combine(folder, f)));
This is how the Uri class works.
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
Updated answer
When referring to base uri it will always be http://example.com/ anything to the right is just path.
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; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With