C # Как я могу проверить, если URL существует / является действительным? - PullRequest
105 голосов
/ 29 мая 2009

Я делаю простую программу в Visual C # 2005, которая ищет символ акций на Yahoo! Финансирование, загрузка исторических данных, а затем построение истории цен для указанного символа тикера.

Я знаю точный URL-адрес, который мне нужен для получения данных, и если пользователь вводит существующий символ тикера (или хотя бы один с данными на Yahoo! Finance), он отлично работает. Однако у меня возникает ошибка во время выполнения, если пользователь создает символ тикера, поскольку программа пытается извлечь данные с несуществующей веб-страницы.

Я использую класс WebClient и использую функцию DownloadString. Я просмотрел все другие функции-члены класса WebClient, но не увидел ничего, что я мог бы использовать для проверки URL.

Как я могу это сделать?

Ответы [ 12 ]

128 голосов
/ 28 сентября 2010

Вот еще одна реализация этого решения:

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/

102 голосов
/ 29 мая 2009

Вы можете выдать "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
}
33 голосов
/ 24 августа 2011

Эти решения довольно хороши, но они забывают, что могут быть другие коды состояния, кроме 200 ОК. Это решение, которое я использовал в производственных средах для мониторинга состояния и тому подобное.

Если на целевой странице имеется перенаправление URL или какое-либо другое условие, возвращаемое значение будет истинным с использованием этого метода. Кроме того, GetResponse () сгенерирует исключение и, следовательно, вы не получите StatusCode для него. Вам нужно перехватить исключение и проверить наличие ProtocolError.

Любой код состояния 400 или 500 вернет false. Все остальные возвращают истину. Этот код легко модифицируется в соответствии с вашими потребностями для конкретных кодов состояния.

/// <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;
}
8 голосов
/ 29 мая 2009

Если я правильно понимаю ваш вопрос, вы можете использовать такой небольшой метод, чтобы получить результаты теста 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;

Вы можете заключить приведенный выше код в метод и использовать его для выполнения проверки. Я надеюсь, что это отвечает на вопрос, который вы задавали.

4 голосов
/ 02 октября 2016

Попробуйте это (убедитесь, что вы используете 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 перешел в него. Если он получает исходный код, он возвращает истину. Если не, возвращает 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");
2 голосов
/ 01 мая 2012

Вот еще один вариант

public static bool UrlIsValid(string url)
{
    bool br = false;
    try {
        IPHostEntry ipHost = Dns.Resolve(url);
        br = true;
    }
    catch (SocketException se) {
        br = false;
    }
    return br;
}
2 голосов
/ 08 мая 2011

Это решение кажется простым для следования:

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 ;
}
1 голос
/ 20 февраля 2012

У меня есть более простой способ определить, является ли URL действительным.

if (Uri.IsWellFormedUriString(uriString, UriKind.RelativeOrAbsolute))
{
   //...
}
0 голосов
/ 21 июня 2018
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");`
}
0 голосов
/ 12 марта 2018

Я всегда обнаруживал, что исключения обрабатываются намного медленнее.

Возможно, менее интенсивный способ принес бы лучший, более быстрый результат?

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"));
...