Program Club

try-catch보다 C #에서 URL을 확인하는 더 좋은 방법은 무엇입니까?

proclub 2020. 11. 22. 20:40
반응형

try-catch보다 C #에서 URL을 확인하는 더 좋은 방법은 무엇입니까?


인터넷에서 이미지를 검색하는 응용 프로그램을 만들고 있습니다. 제대로 작동하지만 응용 프로그램에서 try-catch 문을 사용할 때 속도가 느립니다 (잘못된 지정된 URL에서).

(1) 이것이 URL을 확인하고 잘못된 입력을 처리하는 가장 좋은 방법입니까? 아니면 대신 Regex (또는 다른 방법)를 사용해야합니까?

(2) 텍스트 상자에 http : //를 지정하지 않으면 응용 프로그램이 이미지를 로컬에서 찾으려는 이유는 무엇입니까?

private void btnGetImage_Click(object sender, EventArgs e)
{
    String url = tbxImageURL.Text;
    byte[] imageData = new byte[1];

    using (WebClient client = new WebClient())
    {
        try
        {
            imageData = client.DownloadData(url);
            using (MemoryStream ms = new MemoryStream(imageData))
            {
                try
                {
                    Image image = Image.FromStream(ms);
                    pbxUrlImage.Image = image;
                }
                catch (ArgumentException)
                {
                    MessageBox.Show("Specified image URL had no match", 
                        "Image Not Found", MessageBoxButtons.OK, 
                        MessageBoxIcon.Error);
                }
            }
        }
        catch (ArgumentException)
        {
            MessageBox.Show("Image URL can not be an empty string", 
                "Empty Field", MessageBoxButtons.OK, 
                MessageBoxIcon.Information);
        }
        catch (WebException)
        {
            MessageBox.Show("Image URL is invalid.\nStart with http:// " +
                "and end with\na proper image extension", "Not a valid URL",
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    } // end of outer using statement
} // end of btnGetImage_Click

편집 : Panagiotis Kanavos가 제안한 솔루션을 시도했지만 (노력해 주셔서 감사합니다!), 사용자가 입력 http://하고 더 이상 입력 하지 않으면 if-else 문에만 잡 힙니다 . UriKind.Absolute로 변경하면 빈 문자열도 포착됩니다! 가까이 다가 가기 :) 현재 코드 :

private void btnGetImage_Click(object sender, EventArgs e)
{
    String url = tbxImageURL.Text;
    byte[] imageData = new byte[1];
    Uri myUri;

    // changed to UriKind.Absolute to catch empty string
    if (Uri.TryCreate(url, UriKind.Absolute, out myUri))
    {
        using (WebClient client = new WebClient())
        {
            try
            {
                imageData = client.DownloadData(myUri);
                using (MemoryStream ms = new MemoryStream(imageData))
                {
                    imageData = client.DownloadData(myUri);
                    Image image = Image.FromStream(ms);
                    pbxUrlImage.Image = image;
                }
            }
            catch (ArgumentException)
            {
                MessageBox.Show("Specified image URL had no match",
                    "Image Not Found", MessageBoxButtons.OK, 
                    MessageBoxIcon.Error);
            }
            catch (WebException)
            {
                MessageBox.Show("Image URL is invalid.\nStart with http:// " +
                    "and end with\na proper image extension", 
                    "Not a valid URL",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
    else
    {
        MessageBox.Show("The Image Uri is invalid.\nStart with http:// " +
            "and end with\na proper image extension", "Uri was not created",
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

여기서 뭔가 잘못하고있는 게 분명 해요. :(


사용 Uri.TryCreate은 당신의 URL 문자열이 유효한 URL 인 경우에만 새로운 열린 우리당 개체를 만들 수 있습니다. 문자열이 유효한 URL이 아닌 경우 TryCreate는 false를 반환합니다.

string myString = "http://someUrl";
Uri myUri;
if (Uri.TryCreate(myString, UriKind.RelativeOrAbsolute, out myUri))
{
    //use the uri here
}

최신 정보

TryCreate 또는 Uri 생성자는 "호스트 : www.stackoverflow.com", "호스트 : % 20www.stackoverflow.com"또는 "chrome : about"과 같이 잘못 표시 될 수있는 문자열을 기꺼이 받아들입니다. 사실, 이들은 "http"대신 사용자 정의 스키마를 지정하는 완벽하게 유효한 URI입니다.

Uri.Scheme 속성 의 문서는 "gopher :"(누구나 이것을 기억하십니까?), "news", "mailto", "uuid"와 같은 더 많은 예제를 제공합니다.

응용 프로그램은 MSDN 또는 기타 SO 질문에 설명 된대로 사용자 지정 프로토콜 처리기로 등록 할 수 있습니다 ( 예 : Windows에서 사용자 지정 URL 프로토콜을 어떻게 등록합니까?).

TryCreate는 자신을 특정 체계로 제한하는 방법을 제공하지 않습니다. 코드는 허용 가능한 값이 포함되어 있는지 확인하기 위해 Uri.Scheme 속성을 확인해야합니다.

업데이트 2

이상한 문자열을 전달하면 상대 Uri 객체 "></script><script>alert(9)</script>가 반환 true되고 생성됩니다. Uri.IsWellFormedOriginalString호출 하면 false가 반환됩니다. 따라서 IsWellFormedOriginalString상대 Uris가 제대로 구성되었는지 확인 하려면 전화를해야 할 것입니다 .

반면에 TryCreatewith UriKind.Absolute호출 하면이 경우 false가 반환됩니다.

흥미롭게도 Uri.IsWellFormedUriString은 내부적으로 TryCreate를 호출 한 다음 IsWellFormedOriginalString상대 Uri가 생성 된 경우 의 값을 반환합니다 .


바로 가기는 Uri.IsWellFormedUriString 을 사용하는 것입니다 .

if (Uri.IsWellFormedUriString(myURL, UriKind.RelativeOrAbsolute))
...

Uri를 사용하여 유효한 URL 테스트에 실패하는 몇 가지 예

Uri myUri = null;
if (Uri.TryCreate("Host: www.stackoverflow.com", UriKind.Absolute, out myUri))
{
}

  myUri = null;
if (Uri.TryCreate("Accept: application/json, text/javascript, */*; q=0.01", UriKind.Absolute, out myUri))
{
}

  myUri = null;
if (Uri.TryCreate("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0", UriKind.Absolute, out myUri))
{
}

  myUri = null;
if (Uri.TryCreate("DNT: 1", UriKind.Absolute, out myUri))
{
}

위의 내용을 확인한 후이 모든 말도 안되는 내용이 내 목록보기에 표시된다는 사실에 놀랐습니다. 그러나 모든 것이 검증 테스트를 통과합니다.

이제 위의 유효성 검사 후에 다음을 추가합니다.

url = url.ToLower();
if (url.StartsWith("http://") || url.StartsWith("https://")) return true;

안녕하세요, https http, ftp, sftp, ftps, www로 시작하는 모든 것을 확인합니다.

string regular = @"^(ht|f|sf)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";
string regular123 = @"^(www.)[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";

string myString = textBox1.Text.Trim();
if (Regex.IsMatch(myString, regular))
{
    MessageBox.Show("It is valide url  " + myString);
}
else if (Regex.IsMatch(myString, regular123))
{
    MessageBox.Show("Valide url with www. " + myString);
}
else 
{
    MessageBox.Show("InValide URL  " + myString);
}

또는이 소스 코드 좋은 이미지 유효한 최적화 :

 public static string ValidateImage(string absoluteUrl,string defaultUrl)
        { 
           Uri myUri=null; 
           if (Uri.TryCreate(absoluteUrl, UriKind.Absolute, out myUri))
            {
                using (WebClient client = new WebClient())
                {
                    try
                    {
                        using (Stream stream = client.OpenRead(myUri))
                        {
                            Image image = Image.FromStream(stream);
                            return (image != null) ? absoluteUrl : defaultUrl;
                        }
                    }
                    catch (ArgumentException)
                    {
                        return defaultUrl;
                    }
                    catch (WebException)
                    {
                        return defaultUrl;
                    }
                }
            }
            else
            {
                return defaultUrl;
            }
        }

Sou 및 데모 asp.net mvc 소스 이미지 생성 :

<img src="@ValidateImage("http://example.com/demo.jpg","nophoto.png")"/>

내 솔루션 :

string regular = @"^(ht|f|sf)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&amp;%\$#_]*)?$";
string myString = textBox1.Text.Trim();
if (Regex.IsMatch(myString, regular))
{
    MessageBox.Show("it is valide url  " + myString);
}
else
{
    MessageBox.Show("InValide url  " + myString);
}

그걸 써.....

string myString = http//:google.com;
Uri myUri;
Uri.TryCreate(myString, UriKind.RelativeOrAbsolute, out myUri);
 if (myUri.IsAbsoluteUri == false)
 {
  MessageBox.Show("Please Input Valid Feed Url");
 }

you can use the function Uri.TryCreate As Panagiotis Kanavos suggested if you like to test and create a url or you can use Uri.IsWellFormedUriString function as suggested by Todd Menier if you just wanted to test the validity of Url. this can by handy if you are just validating user input for now and need to create url some time later in life time of your application.

**But my post is for the People, like myself :( , still hitting their heads against .net 1.1 **

both above methods were introduced in .net 2.0 so you guys still have to use try catch method, which, in my opinion, is still far better than using regular expression.

private bool IsValidHTTPURL(string url)
{
    bool result = false;

    try
    {
        Uri uri = new Uri(url);

        result = (uri.Scheme == "http" || uri.Scheme == "https");
    }
    catch (Exception ex) 
    { 
        log.Error("Exception while validating url", ex); 
    }

    return result;
}

I wanted to check if the url also contains a domain extension, it needs to be a valid website url.

This is what i came up with:

 public static bool IsValidUrl(string url)
        {
            if (string.IsNullOrEmpty(url)) { return false;}

            if (!url.StartsWith("http://"))
            {
                url = "http://" + url;    
            }

            Uri outWebsite;

            return Uri.TryCreate(url, UriKind.Absolute, out outWebsite) && outWebsite.Host.Replace("www.", "").Split('.').Count() > 1 && outWebsite.HostNameType == UriHostNameType.Dns && outWebsite.Host.Length > outWebsite.Host.LastIndexOf(".") + 1 && 255 >= url.Length;
        }

I've tested the code with linqpad:

    void Main()
{
        // Errors
        IsValidUrl("www.google/cookie.png").Dump();
        IsValidUrl("1234").Dump();
        IsValidUrl("abcdef").Dump();
        IsValidUrl("abcdef/test.png").Dump();
        IsValidUrl("www.org").Dump();
        IsValidUrl("google").Dump();
        IsValidUrl("google.").Dump();
        IsValidUrl("google/test").Dump();
        IsValidUrl("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0").Dump();
        IsValidUrl("</script><script>alert(9)</script>").Dump();
        IsValidUrl("Accept: application/json, text/javascript, */*; q=0.01").Dump();
        IsValidUrl("DNT: 1").Dump();

        Environment.NewLine.Dump();

        // Success
        IsValidUrl("google.nl").Dump();
        IsValidUrl("www.google.nl").Dump();
        IsValidUrl("http://google.nl").Dump();
        IsValidUrl("http://www.google.nl").Dump();
}

Results:

False False False False False False False False False False False False

True True True True

참고URL : https://stackoverflow.com/questions/3228984/a-better-way-to-validate-url-in-c-sharp-than-try-catch

반응형