C# 如何检查 URL 是否存在/有效?

129

我正在使用Visual C# 2005制作一个简单的程序,它可以在Yahoo! Finance上查找股票代码,下载历史数据,并为指定的股票代号绘制价格历史图表。

我知道需要获取数据的确切URL,如果用户输入一个现有的股票代号(或者至少是在Yahoo! Finance上有数据的),那么程序就能正常工作。但是,如果用户编造一个股票代号,程序会在运行时出现错误,因为程序尝试从不存在的网页中获取数据。

我正在使用WebClient类,并使用DownloadString函数。我浏览了WebClient类的所有其他成员函数,但没有看到任何我可以用来测试URL的东西。

我该怎么办?


1
更新以显示C# 2.0(VS2005)的用法 - Marc Gravell
14个回答

2
很多其他答案都使用已过时的WebRequest。
以下是一种代码最少且使用当前最新类和方法的方法。
我还测试了其他得票最高的函数,但可能会产生虚假结果。 我使用这些URL进行测试,它们指向Visual Studio社区安装程序,在此页面上找到。
//Valid URL
https://aka.ms/vs/17/release/vs_community.exe

//Invalid URL, redirects. Produces false positive on other methods.
https://aka.ms/vs/14/release/vs_community.exe

using System.Net;
using System.Net.Http;

//HttpClient is not meant to be created and disposed frequently.
//Declare it staticly in the class to be reused.
static HttpClient client = new HttpClient();

/// <summary>
/// Checks if a remote file at the <paramref name="url"/> exists, and if access is not restricted.
/// </summary>
/// <param name="url">URL to a remote file.</param>
/// <returns>True if the file at the <paramref name="url"/> is able to be downloaded, false if the file does not exist, or if the file is restricted.</returns>
public static bool IsRemoteFileAvailable(string url)
{
    //Checking if URI is well formed is optional
    Uri uri = new Uri(url);
    if (!uri.IsWellFormedOriginalString())
        return false;

    try
    {
        using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, uri))
        using (HttpResponseMessage response = client.Send(request))
        {
            return response.IsSuccessStatusCode  && response.Content.Headers.ContentLength > 0;
        }
    }
    catch
    {
        return false;
    }
}

请注意,这种方法在.NET Framework中不起作用,因为HttpClient.Send不存在。 要在.NET Framework上使其工作,您需要将client.Send(request)更改为client.SendAsync(request).Result


1

我有一种更简单的方法来确定一个URL是否有效。

if (Uri.IsWellFormedUriString(uriString, UriKind.RelativeOrAbsolute))
{
   //...
}

6
不,这种方法并不检查URL是否真正可访问。 甚至在使用明显不正确的URL Uri.IsWellFormedUriString("http://192.168.1.421/", ...) 时也会返回true。 - zhaorufei

1

继续之前给出的例子,我会说,最佳实践也是像这样使用 using 来包装响应

    public bool IsValidUrl(string url)
    {
         try
         {
             var request = WebRequest.Create(url);
             request.Timeout = 5000;
             request.Method = "HEAD";

             using (var response = (HttpWebResponse)request.GetResponse())
             {
                response.Close();
                return response.StatusCode == HttpStatusCode.OK;
            }
        }
        catch (Exception exception)
        { 
            return false;
        }
   }

1

Web服务器会以HTTP状态码响应请求,表示请求的结果,例如 200 (有时为 202) 表示成功,404 表示未找到等(请在此处查看)。假设URL中的服务器地址部分正确且未出现套接字超时,异常很可能会提示HTTP状态码不是 200。我建议检查异常的类并查看异常是否携带了HTTP状态码。

IIRC - 相关调用将抛出WebException或其子代,检查类名以查看哪个,并在try块中包装调用以捕获该条件。


2
实际上,我记得在200-299范围内的任何内容都表示成功。 - Marc Gravell
Marc,你说得完全正确。我故意避免涉及“错误类别”概念(例如5xx、4xx、3xx、2xx等),因为那会引发一系列问题。即使只是处理标准代码(如200、302、404、500等),也比完全忽略代码要好得多。 - David Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接