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

我正在用 Visual c # 2005编写一个简单的程序,它可以在 Yahoo! Finance 上查找股票代码,下载历史数据,然后绘制指定股票代码的价格历史。

我知道我需要获取数据的确切 URL,如果用户输入一个现有的股票代码(或者至少一个在雅虎财经上的数据) ,它完全可以正常工作。但是,如果用户创建了一个股票代码,程序试图从一个不存在的网页中提取数据,那么我就有一个运行时错误。

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

我怎么能这么做?

294485 次浏览

您可以发出 “头”请求而不是“ GET”? 因此,为了测试一个 URL 而不用花费下载内容的成本:

// using MyClient from linked post
using(var client = new MyClient()) {
client.HeadOnly = true;
// fine, no content downloaded
string s1 = client.DownloadString("http://google.com");
// throws 404
string s2 = client.DownloadString("http://google.com/silly");
}

你会 try/catch周围的 DownloadString检查错误; 没有错误? 它存在..。


使用 C # 2.0(VS2005) :

private bool headOnly;
public bool HeadOnly {
get {return headOnly;}
set {headOnly = value;}
}

还有

using(WebClient client = new MyClient())
{
// code as before
}

网络服务器响应时会显示一个 HTTP状态码,表示请求的结果,例如200(有时是202)表示成功,404-未找到等(见 给你)。假设 URL 的服务器地址部分是正确的,而且你没有得到套接字超时,这个例外很可能告诉你 HTTP状态码不是200。我建议检查异常的类,看看异常是否带有 HTTP状态码。

IIRC-有问题的调用抛出 WebException 或子代。检查类名以查看是哪一个,并将调用包装在 try 块中以捕获条件。

如果我正确理解了你的问题,你可以使用一个像这样的小方法来给你的 URL 测试的结果:

WebRequest webRequest = WebRequest.Create(url);
WebResponse webResponse;
try
{
webResponse = webRequest.GetResponse();
}
catch //If exception thrown then couldn't get response from address
{
return 0;
}
return 1;

您可以将上面的代码封装在一个方法中,并使用它来执行验证。我希望这能回答你的问题。

下面是这个解决方案的另一个实现:

using System.Net;


///
/// Checks the file exists or not.
///
/// The URL of the remote file.
/// True : If the file exits, False if file not exists
private bool RemoteFileExists(string url)
{
try
{
//Creating the HttpWebRequest
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
//Setting the Request method HEAD, you can also use GET too.
request.Method = "HEAD";
//Getting the Web Response.
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
//Returns TRUE if the Status code == 200
response.Close();
return (response.StatusCode == HttpStatusCode.OK);
}
catch
{
//Any exception will returns false.
return false;
}
}

发信人: http://www.dotnetthoughts.net/2009/10/14/how-to-check-remote-file-exists-using-c/

这个解决方案似乎很容易实现:

public static bool isValidURL(string url) {
WebRequest webRequest = WebRequest.Create(url);
WebResponse webResponse;
try
{
webResponse = webRequest.GetResponse();
}
catch //If exception thrown then couldn't get response from address
{
return false ;
}
return true ;
}

这些解决方案非常好,但是他们忘记了除了200 OK 之外还有其他的状态码。这是我在生产环境中用于状态监视等的解决方案。

如果目标页面上有一个 url 重定向或其他条件,那么使用这个方法返回的值将为 true。而且,GetResponse ()会抛出一个异常,因此您不会得到该异常的 StatusCode。您需要捕获异常并检查 ProtocolError。

任何400或500状态码将返回 false。所有其他状态码将返回 true。 此代码很容易修改,以满足您对特定状态代码的需求。

/// <summary>
/// This method will check a url to see that it does not return server or protocol errors
/// </summary>
/// <param name="url">The path to check</param>
/// <returns></returns>
public bool UrlIsValid(string url)
{
try
{
HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
request.Timeout = 5000; //set the timeout to 5 seconds to keep the user from waiting too long for the page to load
request.Method = "HEAD"; //Get only the header information -- no need to download any content


using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
int statusCode = (int)response.StatusCode;
if (statusCode >= 100 && statusCode < 400) //Good requests
{
return true;
}
else if (statusCode >= 500 && statusCode <= 510) //Server Errors
{
//log.Warn(String.Format("The remote server has thrown an internal error. Url is not valid: {0}", url));
Debug.WriteLine(String.Format("The remote server has thrown an internal error. Url is not valid: {0}", url));
return false;
}
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError) //400 errors
{
return false;
}
else
{
log.Warn(String.Format("Unhandled status [{0}] returned for url: {1}", ex.Status, url), ex);
}
}
catch (Exception ex)
{
log.Error(String.Format("Could not test url {0}.", url), ex);
}
return false;
}

我有一个更简单的方法来确定天气一个网址是有效的。

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

还有一个选择

public static bool UrlIsValid(string url)
{
bool br = false;
try {
IPHostEntry ipHost = Dns.Resolve(url);
br = true;
}
catch (SocketException se) {
br = false;
}
return br;
}

根据已经给出的示例,我想说,最好的做法是将响应也包装在这样的使用中

    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;
}
}

试试这个(确保使用 System.Net) :

public bool checkWebsite(string URL) {
try {
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
return true;
}
catch (Exception) {
return false;
}
}

当 checkSite ()函数被调用时,它尝试获取 传入的 URL。如果它得到源代码,它返回 true。如果没有, 结果是假的。

代码示例:

//The checkWebsite command will return true:
bool websiteExists = this.checkWebsite("https://www.google.com");


//The checkWebsite command will return false:
bool websiteExists = this.checkWebsite("https://www.thisisnotarealwebsite.com/fakepage.html");

我总是发现异常处理起来要慢得多。

也许一个不那么密集的方法会产生一个更好、更快、更好的结果?

public bool IsValidUri(Uri uri)
{


using (HttpClient Client = new HttpClient())
{


HttpResponseMessage result = Client.GetAsync(uri).Result;
HttpStatusCode StatusCode = result.StatusCode;


switch (StatusCode)
{


case HttpStatusCode.Accepted:
return true;
case HttpStatusCode.OK:
return true;
default:
return false;
}
}
}

那就用:

IsValidUri(new Uri("http://www.google.com/censorship_algorithm"));
WebRequest request = WebRequest.Create("http://www.google.com");
try
{
request.GetResponse();
}
catch //If exception thrown then couldn't get response from address
{
MessageBox.Show("The URL is incorrect");`
}

很多答案都比 HttpClient 更早(我认为它是在 Visual Studio 2013中引入的) ,或者没有异步/等待功能,所以我决定发布我自己的解决方案:

private static async Task<bool> DoesUrlExists(String url)
{
try
{
using (HttpClient client = new HttpClient())
{
//Do only Head request to avoid download full file
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));


if (response.IsSuccessStatusCode) {
//Url is available is we have a SuccessStatusCode
return true;
}
return false;
}
} catch {
return false;
}
}

我使用 HttpClient.SendAsyncHttpMethod.Head只发出头请求,而不下载整个文件。就像 David 和 Marc 已经说过的,不仅仅有 http 200 for ok,所以我使用 IsSuccessStatusCode来允许所有的成功状态代码。

许多其他的答案使用 WebRequest,现在已经过时了。

下面是一个具有最少代码并使用当前最新类和方法的方法。

我还测试了其他最受欢迎的函数,它们可能产生假阳性。 我测试了这些 URL,它们指向 VisualStudio 社区安装程序 在此页找到

//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;
}
}

只需注意,这对.NETFramework 不起作用,因为 HttpClient.Send 不存在。 要让它在.NETFramework 上工作,您需要将 client.Send(request)更改为 client.SendAsync(request).Result