[英]Path.Combine for URLs (part 2)
一段時間以來,我一直在尋找適用於URL的Path.Combine方法。 這與URL的Path.Combine類似? 有一個很大的區別。
我將以一個例子來說明。 假設我們有一個基本網址: http://example.com/somefolder
: http://example.com/somefolder
和一個文件: foo.txt
。 因此,完整路徑將是: http://example.com/somefolder/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"
...更近,但仍然沒有。
對於踢,我然后嘗試: System.IO.Path.Combine("http://example.com/somefolder/", "foo.txt")
導致"http://example.com/somefolder/foo.txt"
。
最后一個工作,但它基本上在那時進行字符串連接。
所以我認為我有兩個選擇:
我錯過了一個內置的框架方法嗎?
更新:我的用例是下載一堆文件。 我的代碼看起來像這樣:
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之外還處理很多其他協議。
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)));
這就是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 Class
更新的答案
當提到基礎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;
}
}
我有一個靜態方法用於此目的:
// 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;
}
這是一個接近上述答案的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
哦,為什么你們都寫這么復雜的代碼? 這很簡單:
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");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.