Лучший способ проверить URL в C#, чем try-catch?
Я создаю приложение для получения изображения из интернета. Несмотря на то, что он отлично работает, он медленный (на неправильном заданном URL) при использовании операторов try-catch в приложении.
(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 withna 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.Абсолютные ловит пустые строки, а также! Приближение :)
Код на данный момент:
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 withna proper image extension",
"Not a valid URL",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
else
{
MessageBox.Show("The Image Uri is invalid.nStart with http:// " +
"and end withna proper image extension", "Uri was not created",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
должно быть, я делаю что-то неправильно здесь. : (
9 ответов:
использовать 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.Схема property предоставляет больше примеров, таких как" gopher: "(кто-нибудь это помнит?), "новости", "электронной почты", "идентификатор".
приложение может зарегистрироваться в качестве обработчика пользовательского протокола, как описано в MSDN или другие так вопросы, например Как зарегистрировать пользовательский протокол URL в Windows?
TryCreate не предоставляет способ ограничить себя конкретными схемами. Код должен чтобы проверить Uri.Scheme свойство, чтобы убедиться, что он содержит допустимое значение
обновление 2
передача странной строки, как
"></script><script>alert(9)</script>вернутсяtrueи построить относительный объект Uri. Звоню Uri.IsWellFormedOriginalString возвращает false, хотя. Так что вам, вероятно, нужно позвонитьIsWellFormedOriginalStringЕсли вы хотите, чтобы убедиться, что относительные URI хорошо сформированы.С другой стороны, называя
TryCreateСUriKind.Absoluteвозвращает false в этом деле.Интересно, Ури.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)) { }Я был удивлен, что все эти глупости появляются в моем listview после проверки с вышеизложенным. Но все это проходит проверку на достоверность.
теперь я добавляю следующее после вышеуказанной проверки
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\-\.\?\,\'\/\\+&%$#_]*)?$"; string regular123 = @"^(www.)[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\+&%$#_]*)?$"; 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; } }Су и демо 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\-\.\?\,\'\/\\+&%$#_]*)?$"; 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"); }
вы можете использовать функцию
Uri.TryCreateКак Панайотис Канавос предложено, если вы хотите проверить и создать URL-адрес, или вы можете использоватьUri.IsWellFormedUriStringфункция, предложенная Тодд Menier если вы просто хотели проверить правильность 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; }
Я хотел проверить, содержит ли 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; }Я проверил код с 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(); }результаты:
Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложь
Правда Правда Правда Правда