在C#中验证URL的更好方法比try-catch更好吗?

Ben*_*erg 63 c# url image try-catch

我正在构建一个从互联网上检索图像的应用程序.即使它工作正常,但在应用程序中使用try-catch语句时速度很慢(在错误的给定URL上).

(1)这是验证URL和处理错误输入的最佳方法 - 还是应该使用正则表达式(或其他方法)?

(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
Run Code Online (Sandbox Code Playgroud)

编辑: 我尝试了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);
    }
Run Code Online (Sandbox Code Playgroud)

我一定是在做错事.:(

Pan*_*vos 109

仅当您的url字符串是有效URL时,才使用Uri.TryCreate创建新的Uri对象.如果字符串不是有效的URL,TryCreate将返回false.

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

UPDATE

TryCreate或Uri构造函数将很乐意接受可能看似无效的字符串,例如"Host:www.stackoverflow.com","Host:%20www.stackoverflow.com"或"chrome:about".实际上,这些是完全有效的URI,它们指定自定义方案而不是"http".

Uri.Scheme属性的文档提供了更多的例子,比如"gopher:"(有人记得吗?),"news","mailto","uuid".

应用程序可以将自身注册为MSDN或其他SO问题中描述的自定义协议处理程序,例如,如何在Windows中注册自定义URL协议?

TryCreate不提供将自己限制为特定方案的方法.代码需要检查Uri.Scheme属性以确保它包含可接受的值

更新2

传递一个奇怪的字符串"></script><script>alert(9)</script>将返回true并构造一个相对的Uri对象.调用Uri.IsWellFormedOriginalString将返回false.所以IsWellFormedOriginalString如果你想确保相对的Uris形成良好,你可能需要打电话.

另一方面,在这种情况下,调用TryCreatewith UriKind.Absolute将返回false.

有趣的是,Uri.IsWellFormedUriString在内部调用TryCreate,然后返回IsWellFormedOriginalString如果创建了相对Uri 的值.


Tod*_*ier 53

一个捷径就是使用Uri.IsWellFormedUriString:

if (Uri.IsWellFormedUriString(myURL, UriKind.RelativeOrAbsolute))
...
Run Code Online (Sandbox Code Playgroud)

  • 这是实际问到的问题的最佳答案.做得好. (5认同)

Mar*_*tin 5

使用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))
{
}
Run Code Online (Sandbox Code Playgroud)

在通过上述验证后,我很惊讶地将所有这些废话都出现在我的列表视图中.但这一切都通过了验证测试.

现在我在上述验证后添加以下内容

url = url.ToLower();
if (url.StartsWith("http://") || url.StartsWith("https://")) return true;
Run Code Online (Sandbox Code Playgroud)