Лучший способ проверить 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(); }
результаты:
Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложных Ложь
Правда Правда Правда Правда