Лучший способ проверить URL в C #, чем try-catch? - PullRequest
62 голосов
/ 12 июля 2010

Я создаю приложение для извлечения изображения из Интернета. Даже при том, что это работает хорошо, это медленно (на неправильном данном URL), используя операторы try-catch в приложении.

(1) Это лучший способ проверить URL-адрес и обработать неправильный ввод - или я должен вместо этого использовать Regex (или какой-либо другой метод)?

(2) Почему приложение пытается найти изображения локально, если я не указываю http: // в textBox?

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

EDIT: Я попробовал предлагаемое решение Panagiotis Kanavos (спасибо за ваши усилия!), Но оно попадает в оператор if-else, только если пользователь вводит http:// и ничего более. Переход на 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);
    }

Должно быть, я что-то здесь не так делаю. (

Ответы [ 9 ]

109 голосов
/ 12 июля 2010

Используйте Uri.TryCreate , чтобы создать новый объект Uri, только если строка 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 с радостью примут строки, которые могут показаться недействительными, например, "Host: www.stackoverflow.com", "Host:% 20www.stackoverflow.com "или" chrome: about ".Фактически, это совершенно допустимые URI, которые задают пользовательскую схему вместо «http».

В документации к свойству Uri.Scheme приведены дополнительные примеры, например "gopher:" (кто-нибудь помнит это?), "News", "mailto", "uuid".

Приложение может зарегистрироваться как обработчик настраиваемого протокола, как описано в MSDN или других вопросах SO, например Как зарегистрировать настраиваемый протокол URL в Windows?

TryCreate не позволяет ограничивать себя конкретными схемами.Код должен проверить свойство Uri.Scheme, чтобы убедиться, что оно содержит допустимое значение

ОБНОВЛЕНИЕ 2

Передача странной строки, такой как "></script><script>alert(9)</script>, вернет trueи построить относительный объект Uri.Вызов Uri.IsWellFormedOriginalString все же вернет false.Поэтому вам, вероятно, нужно позвонить IsWellFormedOriginalString, если вы хотите убедиться, что относительный Uris правильно сформирован.

С другой стороны, вызов TryCreate с UriKind.Absolute вернет false в этом случае.

Интересно, что Uri.IsWellFormedUriString вызывает TryCreate внутренне, а затем возвращает значение IsWellFormedOriginalString, если был создан относительный Uri.

52 голосов
/ 02 ноября 2011

Ярлык будет использовать Uri.IsWellFormedUriString :

if (Uri.IsWellFormedUriString(myURL, UriKind.RelativeOrAbsolute))
...
5 голосов
/ 19 декабря 2012

Некоторые примеры использования 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;
4 голосов
/ 23 декабря 2011

Привет, вы проверяете 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);
}
3 голосов
/ 01 января 2015

Используйте это .....

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");
 }
3 голосов
/ 22 декабря 2011

Мое решение:

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);
}
3 голосов
/ 01 декабря 2011

Или этот исходный код хорошего изображения действительной оптимизации:

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

Создано исходное изображение mvc для su и demo asp.net:

<img src="@ValidateImage("http://example.com/demo.jpg","nophoto.png")"/>
2 голосов
/ 02 декабря 2013

Вы можете использовать функцию Uri.TryCreate Как Рекомендуется Panagiotis Kanavos , если вы хотите протестировать и создать URL-адрес, или вы можете использовать Uri.IsWellFormedUriString функцию, предложенную Тоддом Меньером , если Вы просто хотели проверить действительность URL. Это может быть удобно, если вы сейчас только проверяете пользовательский ввод и вам нужно создать URL-адрес через некоторое время после запуска вашего приложения.

** Но мой пост для Людей, как и я :(, все еще бьющихся по головам против .net 1.1 **

оба вышеуказанных метода были введены в .net 2.0, поэтому вам, ребята, все еще нужно использовать метод try catch, который, на мой взгляд, все же намного лучше, чем использование регулярных выражений.

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;
}
1 голос
/ 07 июня 2015

Я хотел проверить, содержит ли URL-адрес расширение домена, это должен быть действительный URL-адрес веб-сайта.

Вот что я придумал:

 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 'мы проверили код с помощью 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();
}

Результаты:

Ложь Ложь Ложь Ложь Ложь Ложь Ложь Ложь Ложь Ложь Ложь

Ложь Истинный Истинный

...