インターネットから画像を取得するアプリケーションを作成しています。正常に動作しますが、アプリケーションでtry-catchステートメントを使用すると、(間違ったURLで)遅くなります。
(1)これはURLを検証し、間違った入力を処理するための最良の方法ですか?または、代わりにRegex(または他の方法)を使用する必要がありますか?
(2)textBoxで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
編集:パナギオティスカナヴォスによる提案された解決策を試しました(努力していただきありがとうございます!)が、ユーザーが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);
}
ここで何か間違ったことをしているに違いない。 :(
ri.TryCreate を使用して、URL文字列が有効なURLである場合にのみ新しいUriオブジェクトを作成します。文字列が有効なURLでない場合、TryCreateはfalseを返します。
_string myString = "http://someUrl";
Uri myUri;
if (Uri.TryCreate(myString, UriKind.RelativeOrAbsolute, out myUri))
{
//use the uri here
}
_
[〜#〜] update [〜#〜]
TryCreateまたはUriコンストラクターは、「Host:www.stackoverflow.com」、「Host:%20www.stackoverflow.com」、「chrome:about」など、無効と思われる文字列を喜んで受け入れます。実際、これらは「http」の代わりにカスタムスキームを指定する完全に有効なURIです。
ri.Scheme プロパティのドキュメントには、「Gopher:」(誰もがこれを覚えていますか?)、「news」、「mailto」、「uuid」などの例があります。
[〜#〜] msdn [〜#〜] または他のSOの質問、たとえば WindowsでカスタムURLプロトコルを登録するにはどうすればよいですか?
TryCreateには、特定のスキームに制限する方法はありません。コードはUri.Schemeプロパティをチェックして、許容値が含まれていることを確認する必要があります
更新2
"></script><script>alert(9)</script>
のような奇妙な文字列を渡すと、true
が返され、相対的なUriオブジェクトが構築されます。 ri.IsWellFormedOriginalString を呼び出すと、falseが返されます。したがって、相対Urisの形式が正しいことを確認する場合は、おそらくIsWellFormedOriginalString
を呼び出す必要があります。
一方、TryCreate
を_UriKind.Absolute
_で呼び出すと、この場合falseが返されます。
興味深いことに、Uri.IsWellFormedUriStringは内部でTryCreateを呼び出し、相対Uriが作成された場合はIsWellFormedOriginalString
の値を返します。
ショートカットは ri.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\-\.\?\,\'\/\\\+&%\$#_]*)?$";
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);
}
これを使って.....
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");
}
または、このソースコードの良い画像の有効な最適化:
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\-\.\?\,\'\/\\\+&%\$#_]*)?$";
string myString = textBox1.Text.Trim();
if (Regex.IsMatch(myString, regular))
{
MessageBox.Show("it is valide url " + myString);
}
else
{
MessageBox.Show("InValide url " + myString);
}
関数を使用することができます_Uri.TryCreate
_ As Panagiotis Kanavos URLをテストして作成する場合、または_Uri.IsWellFormedUriString
_関数を使用して Todd 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にドメイン拡張子も含まれているかどうかを確認したかったため、有効なWebサイトの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();
}
結果:
False False False False False False False False False False False False False False
True True True True