etc./StackOverFlow

URL에 대한 Path.Combine?

청렴결백한 만능 재주꾼 2023. 4. 15. 23:22
반응형

질문자 :Brian MacKay


Path.Combine 은 편리하지만 URL 에 대한 .NET 프레임워크에 유사한 기능이 있습니까?

다음과 같은 구문을 찾고 있습니다.

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

다음을 반환합니다.

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



Uri 에는 이 작업을 수행하는 생성자가 있습니다. new Uri(Uri baseUri, string relativeUri)

다음은 예입니다.

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

편집자의 참고 사항: 이 방법은 예상대로 작동하지 않습니다. 경우에 따라 baseUri의 일부를 잘라낼 수 있습니다. 의견 및 기타 답변을 참조하십시오.


Joel Beckham

이것은 적절하게 간단한 해결책일 수 있습니다.

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

Matthew Sharpe

Uri.TryCreate( ... ) .

 Uri result = null; if (Uri.TryCreate(new Uri("http://msdn.microsoft.com/en-us/library/"), "/en-us/library/system.uri.trycreate.aspx", out result)) { Console.WriteLine(result); }

반환됩니다:

http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx


Ryan Cook

여기에 이미 훌륭한 답변이 있습니다. 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 가 생성됩니다.

Uris 대신 문자열로 작업하려는 경우 다음도 동일한 결과를 생성하므로 필요에 맞게 조정하기만 하면 됩니다.

 public string JoinUriSegments(string uri, params string[] segments) { if (string.IsNullOrWhiteSpace(uri)) return null; if (segments == null || segments.Length == 0) return uri; return segments.Aggregate(uri, (current, segment) => $"{current.TrimEnd('/')}/{segment.TrimStart('/')}"); } var uri = JoinUriSegements("http://example.com/subpath/", "/part1/", "part2");

Ales Potocnik Hahonina

위의 토드 미니 어의 주석입니다 것을 Flurl가 포함 Url.Combine .

자세한 내용은:

Url.Combine은 기본적으로 URL에 대한 Path.Combine이며 부분 사이에 단 하나의 구분 문자를 보장합니다.

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

NuGet에서 Flurl.Http 가져오기 :

PM> 설치 패키지 Flurl.Http

또는 HTTP 기능이 없는 독립 실행형 URL 빌더를 가져옵니다.

PM> 설치 패키지 Flurl


Michael Freidgeim

Ryan Cook의 대답은 내가 추구하는 것에 가깝고 다른 개발자에게 더 적합할 수 있습니다. 그러나 문자열의 시작 부분에 http://를 추가하고 일반적으로 내가 원하는 것보다 약간 더 많은 형식을 지정합니다.

또한 내 사용 사례의 경우 상대 경로를 확인하는 것은 중요하지 않습니다.

mdsharp의 답변에는 좋은 아이디어의 씨앗도 포함되어 있지만 실제 구현을 완료하려면 몇 가지 세부 사항이 더 필요했습니다. 이것은 그것을 구체화하려는 시도입니다 (그리고 프로덕션에서 이것을 사용하고 있습니다).

씨#

 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

Brian MacKay

"|"와 같은 문자가 있을 수 있으므로 Path.Combine이 작동하지 않습니다. QueryString 인수 및 따라서 URL에서 ArgumentException이 발생합니다.

먼저 http://www.mediawiki.org/wiki/Special:SpecialPages 와 같은 URI 때문에 실패한 Uri(Uri baseUri, string relativeUri) 접근 방식을 시도했습니다.

 new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")

구성표를 나타내는 Special 뒤에 콜론이 있기 때문에 Special:SpecialPages가 생성됩니다.

그래서 마침내 mdsharpe/Brian MacKays 경로를 선택하고 여러 URI 부분으로 작업하기 위해 조금 더 개발해야 했습니다.

 public static string CombineUri(params string[] uriParts) { string uri = string.Empty; if (uriParts != null && uriParts.Length > 0) { 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; }

사용법: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")


Mike Fuchs

귀하가 제공한 샘플 URL 을 기반으로 귀하의 사이트와 관련된 URL을 결합하려고 한다고 가정하겠습니다.

이 가정을 바탕으로 "Path.Combine이 편리합니다. URL 프레임워크에 유사한 기능 이 있습니까?"라는 질문에 대한 가장 적절한 응답으로 이 솔루션을 제안합니다.

URL 프레임워크에 유사한 기능 이 있기 때문에 올바른 방법은 "VirtualPathUtility.Combine" 방법이라고 제안합니다. 다음은 MSDN 참조 링크입니다. VirtualPathUtility.Combine 메서드

한 가지 주의 사항이 있습니다. 이 방법은 귀하의 사이트와 관련된 URL에만 적용됩니다(즉, 다른 웹 사이트에 대한 링크를 생성하는 데 사용할 수 없습니다. 예: var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets"); ).


Jeronimo Colon III

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

JeremyWeir

방금 작은 확장 방법을 만들었습니다.

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

urza

재치 있는 예, Ryan은 함수에 대한 링크로 끝납니다. 잘 했어요.

한 가지 권장 사항 Brian: 이 코드를 함수로 래핑하는 경우 UriBuilder를 사용하여 TryCreate 호출 전에 기본 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"); }

mtazva

이들을 결합하고 항상 올바른지 확인하는 쉬운 방법은 다음과 같습니다.

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

Alex

URL의 여러 부분을 결합하는 것은 약간 까다로울 수 있습니다. 두 매개 변수 생성자 Uri(baseUri, relativeUri) 를 사용하거나 Uri.TryCreate() 유틸리티 함수를 사용할 수 있습니다.

baseUri , 즉 http://google.com/some/thing 에서 http://google.com 로의 상대적인 부분을 계속 자르기 때문에 잘못된 결과를 반환할 수 있습니다. http://google.com .

여러 부분을 최종 URL로 결합하려면 아래 두 가지 기능을 복사하면 됩니다.

 public static string Combine(params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; var urlBuilder = new StringBuilder(); foreach (var part in parts) { var tempUrl = tryCreateRelativeOrAbsolute(part); urlBuilder.Append(tempUrl); } return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToString()); } private static string tryCreateRelativeOrAbsolute(string s) { System.Uri uri; System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri); string tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToString()); return tempUrl; }

사용법을 보여주기 위한 단위 테스트가 포함된 전체 코드는 https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs에서 찾을 수 있습니다.

가장 일반적인 세 가지 경우를 다루는 단위 테스트가 있습니다.

여기에 이미지 설명 입력


Believe2014

다른 답변에서 볼 수 있듯이 new Uri() 또는 TryCreate() 가 틱을 수행할 수 있습니다. 그러나 기본 Uri는 / / 시작하지 않아야 합니다. 그렇지 않으면 기본 URL의 후행 부분을 제거합니다.

나는 이것이 확장 방법으로 가장 잘 수행된다고 생각합니다.

 public static Uri Append(this Uri uri, string relativePath) { var baseUri = uri.AbsoluteUri.EndsWith('/') ? uri : new Uri(uri.AbsoluteUri + '/'); var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath; return new Uri(baseUri, relative); }

그리고 그것을 사용하려면:

 var baseUri = new Uri("http://test.com/test/"); var combinedUri = baseUri.Append("/Do/Something");

성능 면에서 이것은 많은 구문 분석과 검증을 수행하는 Uri 클래스 때문에 필요한 것보다 더 많은 리소스를 소비합니다. 매우 거친 프로파일링(디버그)은 약 2초 만에 백만 개의 작업을 수행했습니다. 이것은 대부분의 시나리오에서 작동하지만 더 효율적이려면 모든 것을 문자열로 조작하는 것이 좋습니다. 100만 작업에 125밀리초가 걸립니다. 즉

 public static string Append(this Uri uri, string relativePath) { //avoid the use of Uri as it's not needed, and adds a bit of overhead. var absoluteUri = uri.AbsoluteUri; //a calculated property, better cache it var baseUri = absoluteUri.EndsWith('/') ? absoluteUri : absoluteUri + '/'; var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath; return baseUri + relative; }

그리고 여전히 URI를 반환하려는 경우 100만 작업에 약 600밀리초가 걸립니다.

 public static Uri AppendUri(this Uri uri, string relativePath) { //avoid the use of Uri as it's not needed, and adds a bit of overhead. var absoluteUri = uri.AbsoluteUri; //a calculated property, better cache it var baseUri = absoluteUri.EndsWith('/') ? absoluteUri : absoluteUri + '/'; var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath; return new Uri(baseUri + relative); }

이게 도움이 되길 바란다.


Mahmoud Hanafy

원하는 만큼 많은 경로 세그먼트를 처리할 수 있으므로 이것이 더 많은 유연성을 제공해야 한다고 생각합니다.

 public static string UrlCombine(this string baseUrl, params string[] segments) => string.Join("/", new[] { baseUrl.TrimEnd('/') }.Concat(segments.Select(s => s.Trim('/'))));

GoldenAge

UriBuilder 가 이런 종류의 일에 정말 잘 작동한다는 것을 발견했습니다.

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

더 많은 생성자와 설명서는 UriBuilder 클래스 - MSDN 을 참조하세요.


javajavajavajavajava

Flurl과 같은 종속성을 원하지 않는 경우 해당 소스 코드를 사용할 수 있습니다.

 /// <summary> /// Basically a Path.Combine for URLs. Ensures exactly one '/' separates each segment, /// and exactly on '&amp;' separates each query parameter. /// URL-encodes illegal characters but not reserved characters. /// </summary> /// <param name="parts">URL parts to combine.</param> public static string Combine(params string[] parts) { if (parts == null) throw new ArgumentNullException(nameof(parts)); string result = ""; bool inQuery = false, inFragment = false; string CombineEnsureSingleSeparator(string a, string b, char separator) { if (string.IsNullOrEmpty(a)) return b; if (string.IsNullOrEmpty(b)) return a; return a.TrimEnd(separator) + separator + b.TrimStart(separator); } foreach (var part in parts) { if (string.IsNullOrEmpty(part)) continue; if (result.EndsWith("?") || part.StartsWith("?")) result = CombineEnsureSingleSeparator(result, part, '?'); else if (result.EndsWith("#") || part.StartsWith("#")) result = CombineEnsureSingleSeparator(result, part, '#'); else if (inFragment) result += part; else if (inQuery) result = CombineEnsureSingleSeparator(result, part, '&'); else result = CombineEnsureSingleSeparator(result, part, '/'); if (part.Contains("#")) { inQuery = false; inFragment = true; } else if (!inFragment && part.Contains("?")) { inQuery = true; } } return EncodeIllegalCharacters(result); } /// <summary> /// URL-encodes characters in a string that are neither reserved nor unreserved. Avoids encoding reserved characters such as '/' and '?'. Avoids encoding '%' if it begins a %-hex-hex sequence (ie avoids double-encoding). /// </summary> /// <param name="s">The string to encode.</param> /// <param name="encodeSpaceAsPlus">If true, spaces will be encoded as + signs. Otherwise, they'll be encoded as %20.</param> /// <returns>The encoded URL.</returns> public static string EncodeIllegalCharacters(string s, bool encodeSpaceAsPlus = false) { if (string.IsNullOrEmpty(s)) return s; if (encodeSpaceAsPlus) s = s.Replace(" ", "+"); // Uri.EscapeUriString mostly does what we want - encodes illegal characters only - but it has a quirk // in that % isn't illegal if it's the start of a %-encoded sequence https://stackoverflow.com/a/47636037/62600 // no % characters, so avoid the regex overhead if (!s.Contains("%")) return Uri.EscapeUriString(s); // pick out all %-hex-hex matches and avoid double-encoding return Regex.Replace(s, "(.*?)((%[0-9A-Fa-f]{2})|$)", c => { var a = c.Groups[1].Value; // group 1 is a sequence with no %-encoding - encode illegal characters var b = c.Groups[2].Value; // group 2 is a valid 3-character %-encoded sequence - leave it alone! return Uri.EscapeUriString(a) + b; }); }

er sd

다음이 유용하고 다음과 같은 기능이 있습니다.

  • null 또는 공백에 대한 throw
  • 여러 URL 세그먼트에 대해 여러 params 매개변수를 사용합니다.
  • null 또는 비어 있음

수업

 public static class UrlPath { private static string InternalCombine(string source, string dest) { if (string.IsNullOrWhiteSpace(source)) throw new ArgumentException("Cannot be null or white space", nameof(source)); if (string.IsNullOrWhiteSpace(dest)) throw new ArgumentException("Cannot be null or white space", nameof(dest)); return $"{source.TrimEnd('/', '\\')}/{dest.TrimStart('/', '\\')}"; } public static string Combine(string source, params string[] args) => args.Aggregate(source, InternalCombine); }

테스트

 UrlPath.Combine("test1", "test2"); UrlPath.Combine("test1//", "test2"); UrlPath.Combine("test1", "/test2"); // Result = test1/test2 UrlPath.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ; // Result = test1/test2/test3 UrlPath.Combine("/test1/", "/test2/", null); UrlPath.Combine("", "/test2/"); UrlPath.Combine("/test1/", null); // Throws an ArgumentException

TheGeneral

내 일반적인 솔루션:

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

Alex Titarenko

다음은 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); }

출처: GitHub


user3638471

나는 당신의 삶을 더 쉽게 만들어줄 이 기능을 만들었습니다:

 /// <summary> /// The ultimate Path combiner of all time /// </summary> /// <param name="IsURL"> /// true - if the paths are Internet URLs, false - if the paths are local URLs, this is very important as this will be used to decide which separator will be used. /// </param> /// <param name="IsRelative">Just adds the separator at the beginning</param> /// <param name="IsFixInternal">Fix the paths from within (by removing duplicate separators and correcting the separators)</param> /// <param name="parts">The paths to combine</param> /// <returns>the combined path</returns> public static string PathCombine(bool IsURL , bool IsRelative , bool IsFixInternal , params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; char separator = IsURL ? '/' : '\\'; if (parts.Length == 1 && IsFixInternal) { string validsingle; if (IsURL) { validsingle = parts[0].Replace('\\' , '/'); } else { validsingle = parts[0].Replace('/' , '\\'); } validsingle = validsingle.Trim(separator); return (IsRelative ? separator.ToString() : string.Empty) + validsingle; } string final = parts .Aggregate ( (string first , string second) => { string validfirst; string validsecond; if (IsURL) { validfirst = first.Replace('\\' , '/'); validsecond = second.Replace('\\' , '/'); } else { validfirst = first.Replace('/' , '\\'); validsecond = second.Replace('/' , '\\'); } var prefix = string.Empty; if (IsFixInternal) { if (IsURL) { if (validfirst.Contains("://")) { var tofix = validfirst.Substring(validfirst.IndexOf("://") + 3); prefix = validfirst.Replace(tofix , string.Empty).TrimStart(separator); var tofixlist = tofix.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = separator + string.Join(separator.ToString() , tofixlist); } else { var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = string.Join(separator.ToString() , firstlist); } var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validsecond = string.Join(separator.ToString() , secondlist); } else { var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries); validfirst = string.Join(separator.ToString() , firstlist); validsecond = string.Join(separator.ToString() , secondlist); } } return prefix + validfirst.Trim(separator) + separator + validsecond.Trim(separator); } ); return (IsRelative ? separator.ToString() : string.Empty) + final; }

URL은 물론 일반 경로에서도 작동합니다.

용법:

 // Fixes internal paths Console.WriteLine(PathCombine(true , true , true , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); // Result: /folder 1/folder2/folder3/somefile.ext // Doesn't fix internal paths Console.WriteLine(PathCombine(true , true , false , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); //result : /folder 1//////////folder2////folder3/somefile.ext // Don't worry about URL prefixes when fixing internal paths Console.WriteLine(PathCombine(true , false , true , @"/\/\/https:/\/\/\lul.com\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\")); // Result: https://lul.com/folder2/folder3/somefile.ext Console.WriteLine(PathCombine(false , true , true , @"../../../\\..\...\./../somepath" , @"anotherpath")); // Result: \..\..\..\..\...\.\..\somepath\anotherpath

Ahmed Fwela

Uri 생성자가 '\'를 '/'로 바꾸는 것을 발견했습니다. Uri 생성자와 함께 Path.Combine 을 사용할 수도 있습니다.

 Uri baseUri = new Uri("http://MyUrl.com"); string path = Path.Combine("Images", "Image.jpg"); Uri myUri = new Uri(baseUri, path);

skippy

다음을 사용하지 않는 이유는 무엇입니까?

 System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")

Andreas

Flurl과 같은 타사 종속성을 추가하거나 사용자 지정 확장 메서드를 생성하지 않으려면 ASP.NET Core(Microsoft.Owin에서도 사용 가능)에서 구축을 목적으로 PathString URI 경로. UriUriBuilder 조합을 사용하여 전체 URI를 만들 수 있습니다.

이 경우 다음과 같습니다.

 new Uri(new UriBuilder("http", "MyUrl.com").Uri, new PathString("/Images").Add("/Image.jpg").ToString())

이렇게 하면 기본 URL에 구분 기호를 지정하지 않고도 모든 구성 요소가 제공됩니다. 불행히도 PathString/ 가 각 문자열 앞에 추가되어야 합니다. 그렇지 않으면 실제로 ArgumentException ! 그러나 최소한 쉽게 단위 테스트가 가능한 방식으로 URI를 결정적으로 구축할 수 있습니다.


Neo

그래서 저는 UriBuilder를 사용한 모든 사람들과 유사한 또 다른 접근 방식을 가지고 있습니다.

javajavajavajavajava처럼 BaseUrl(경로의 일부를 포함할 수 있음 - 예: http://mybaseurl.com/dev/ )을 분할 하고 싶지 않았습니다.

다음 스니펫은 코드 + 테스트를 보여줍니다.

주의: 이 솔루션은 호스트를 소문자로 만들고 포트를 추가합니다. 이것이 원하지 않는 경우, 예를 들어 UriBuilder Uri 속성을 활용하여 문자열 표현을 작성할 수 있습니다.

 public class Tests { public static string CombineUrl (string baseUrl, string path) { var uriBuilder = new UriBuilder (baseUrl); uriBuilder.Path = Path.Combine (uriBuilder.Path, path); return uriBuilder.ToString(); } [TestCase("http://MyUrl.com/", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")] [TestCase("http://MyUrl.com/basePath", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")] [TestCase("http://MyUrl.com/basePath", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")] [TestCase("http://MyUrl.com/basePath/", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")] public void Test1 (string baseUrl, string path, string expected) { var result = CombineUrl (baseUrl, path); Assert.That (result, Is.EqualTo (expected)); } }

Windows 10에서 .NET Core 2.1로 테스트했습니다.

이것이 작동하는 이유는 무엇입니까?

Path.Combine 를 반환하더라도 Path 의 Setter에서 이 경우를 처리합니다.

https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/src/System/UriBuilder.cs string.Replace 호출에 주의)

 [AllowNull] public string Path { get { return _path; } set { if ((value == null) || (value.Length == 0)) { value = "/"; } _path = Uri.InternalEscapeString(value.Replace('\\', '/')); _changed = true; } }

이것이 최선의 방법입니까?

확실히 이 솔루션은 꽤 자명합니다(적어도 제 생각에는). 그러나 당신은 .NET API의 문서화되지 않은(적어도 빠른 Google 검색으로 아무것도 찾지 못한) "기능"에 의존하고 있습니다. 이것은 향후 릴리스에서 변경될 수 있으므로 테스트가 포함된 방법을 다루십시오.

테스트에있다 https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/tests/FunctionalTests/UriBuilderTests.cs은 ( Path_Get_Set )하는 검사의 경우 \ 정확하게 변환된다.

참고 사항: System.Uri ctor에 사용되는 경우 UriBuilder.Uri 속성으로 직접 작업할 수도 있습니다.


Tobias Schwarzinger

간단한 하나의 라이너:

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

@Matt Sharpe의 답변에서 영감을 얻었습니다.


Nick N.

URL을 URI와 결합할 때의 규칙

이상한 행동을 피하기 위해 따라야 할 한 가지 규칙이 있습니다.

  • 경로(디렉토리)는 '/'로 끝나야 합니다. 경로가 '/' 없이 끝나는 경우 마지막 부분은 파일 이름으로 처리되며 다음 URL 부분과 결합하려고 할 때 연결됩니다.
  • 한 가지 예외가 있습니다. 기본 URL 주소(디렉토리 정보 제외)는 '/'로 끝날 필요가 없습니다.
  • 경로 부분은 '/'로 시작하면 안 됩니다. '/'로 시작하면 URL의 모든 기존 상대 정보가 삭제됩니다... string.Empty 추가하면 빈 부분 경로가 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(); });

baHI

여기 내 접근 방식이 있으며 나 자신에게도 사용할 것입니다.

 public static string UrlCombine(string part1, string part2) { string newPart1 = string.Empty; string newPart2 = string.Empty; string seperator = "/"; // If either part1 or part 2 is empty, // we don't need to combine with seperator if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2)) { seperator = 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, seperator, newPart2); }

Amit Bhagat

이것을 사용하십시오:

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

Martin Murphy

그 가치를 위해 여기에 몇 가지 확장 방법이 있습니다. 첫 번째는 경로를 결합하고 두 번째는 URL에 매개변수를 추가합니다.

 public static string CombineUrl(this string root, string path, params string[] paths) { if (string.IsNullOrWhiteSpace(path)) { return root; } Uri baseUri = new Uri(root); Uri combinedPaths = new Uri(baseUri, path); foreach (string extendedPath in paths) { combinedPaths = new Uri(combinedPaths, extendedPath); } return combinedPaths.AbsoluteUri; } public static string AddUrlParams(this string url, Dictionary<string, string> parameters) { if (parameters == null || !parameters.Keys.Any()) { return url; } var tempUrl = new StringBuilder($"{url}?"); int count = 0; foreach (KeyValuePair<string, string> parameter in parameters) { if (count > 0) { tempUrl.Append("&"); } tempUrl.Append($"{WebUtility.UrlEncode(parameter.Key)}={WebUtility.UrlEncode(parameter.Value)}"); count++; } return tempUrl.ToString(); }

LawMan

출처 : http:www.stackoverflow.com/questions/372865/path-combine-for-urls

반응형