[英]C# How can I check if a URL exists/is valid?
我正在 Visual c# 2005 中制作一个简单的程序,它在 Yahoo、Finance 上查找股票代码,下载历史数据。 然后绘制指定股票代码的价格历史。
我知道我需要获取数据的确切 URL,如果用户输入现有的股票代码(或至少一个带有 Yahoo.Finance 上的数据),它工作得很好,但是,如果用户组成一个股票代码。 因为程序试图从不存在的 web 页面中提取数据。
我正在使用 WebClient class,并使用 DownloadString function。 我查看了 WebClient class 的所有其他成员函数,但没有看到可以用来测试 URL 的任何东西。
我怎样才能做到这一点?
这是此解决方案的另一个实现:
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/
您可以发出“HEAD”请求而不是“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
}
这些解决方案都不错,但是他们忘记了可能还有其他状态码而不是 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;
}
如果我正确理解您的问题,您可以使用这样的小方法来为您提供 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;
您可以将上述代码包装在一个方法中并使用它来执行验证。 我希望这能回答你提出的问题。
试试这个(确保你使用 System.Net):
public bool checkWebsite(string URL) {
try {
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
return true;
}
catch (Exception) {
return false;
}
}
当 checkWebsite() 函数被调用时,它会尝试获取传递给它的 URL 的源代码。 如果它获取源代码,则返回 true。 如果不是,则返回 false。
代码示例:
//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 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 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");`
}
这个解决方案似乎很容易遵循:
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 ;
}
继已经给出的示例之后,我想说,最好的做法是也将响应包装在这样的使用中
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;
}
}
Web 服务器以 HTTP 状态代码响应,指示请求的结果,例如 200(有时为 202)表示成功,404 - 未找到等(请参阅此处)。 假设 URL 的服务器地址部分是正确的并且您没有收到套接字超时,则异常很可能告诉您 HTTP 状态代码不是 200。我建议检查异常的类并查看异常是否携带HTTP 状态代码。
IIRC - 有问题的调用引发 WebException 或后代。 检查类名以查看是哪一个并将调用包装在 try 块中以捕获条件。
我有一种更简单的方法来确定 url 的天气是否有效。
if (Uri.IsWellFormedUriString(uriString, UriKind.RelativeOrAbsolute))
{
//...
}
很多答案都比 HttpClient 旧(我认为它是在 Visual Studio 2013 中引入的)或者没有 async/await 功能,所以我决定发布我自己的解决方案:
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.SendAsync
和HttpMethod.Head
来只发出一个头请求,而不是下载整个文件。 就像 David 和 Marc 已经说过的,不仅有 http 200 可以,所以我使用IsSuccessStatusCode
来允许所有成功状态代码。
许多其他答案正在使用现已过时的 WebRequest。
这是一个具有最少代码并使用当前最新的类和方法的方法。
我还测试了其他可能产生误报的投票最多的函数。 我使用这些指向 Visual Studio 社区安装程序的 URL 进行了测试, 可在此页面上找到。
//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 框架,因为 HttpClient.Send 不存在。 要让它在 .NET 框架上运行,您需要将client.Send(request)
更改为 client.SendAsync(request) client.SendAsync(request).Result
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.