57

I know I can locally, on my filesystem, check if a file exists:

if(File.Exists(path))

Can I check at a particular remote URL?

mrblah
  • 99,669
  • 140
  • 310
  • 420
  • See also here for mixing WebClient and HEAD in a single answer: http://stackoverflow.com/questions/153451#156750 – Marc Gravell Dec 30 '09 at 13:26
  • Marc, why would using a custom class be better in this case? [Later on](http://stackoverflow.com/a/924682/274502) you even suggest on using `try` / `catch`. – cregox Aug 17 '12 at 21:00

11 Answers11

95

If you're attempting to verify the existence of a web resource, I would recommend using the HttpWebRequest class. This will allow you to send a HEAD request to the URL in question. Only the response headers will be returned, even if the resource exists.

var url = "http://www.domain.com/image.png";
HttpWebResponse response = null;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";


try
{
    response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
    /* A WebException will be thrown if the status of the response is not `200 OK` */
}
finally
{
    // Don't forget to close your response.
    if (response != null)
    {
        response.Close();
    }
}

Of course, if you want to download the resource if it exists it would most likely be more efficient to send a GET request instead (by not setting the Method property to "HEAD", or by using the WebClient class).

Ravenix
  • 1,010
  • 4
  • 15
  • 40
Justin Rusbatch
  • 3,992
  • 2
  • 25
  • 43
  • 13
    I'd recommend checking for a 404 rather than just any 'ol error code. If it's a 500, for example, then it might be that the "file" exists, but that the server encountered (a perhaps temporary) error when servicing the request. To check for 404s, make sure to cast `ex.Response` to `HttpWebResponse`, and then you can compare `StatusCode` to `HttpStatusCode.NotFound`. – Kirk Woll Nov 14 '13 at 22:29
  • I'm surprised I'm the first one to note that `response` should be Disposed! – Mmm Jul 09 '19 at 19:40
  • If you use a using on `response = (HttpWebResponse)request.GetResponse();` it will be disposed of automatically. – PRMan Apr 16 '21 at 21:10
19

If you want to just copy & paste Justin's code and get a method to use, here's how I've implemented it:

using System.Net;

public class MyClass {
    static public bool URLExists (string url) {
        bool result = false;

        WebRequest webRequest = WebRequest.Create(url);
        webRequest.Timeout = 1200; // miliseconds
        webRequest.Method = "HEAD";

        HttpWebResponse response = null;

        try {
            response = (HttpWebResponse)webRequest.GetResponse();
            result = true;
        } catch (WebException webException) {
            Debug.Log(url +" doesn't exist: "+ webException.Message);
        } finally {
            if (response != null) {
                response.Close();
            }
        }

        return result;
    }
}

I'll keep his observation:

If you want to download the resource, and it exists, it would be more efficient to send a GET request instead by not setting the Method property to "HEAD" or by using the WebClient class.

cregox
  • 17,674
  • 15
  • 85
  • 116
12

Below is a simplified version of the code:

public bool URLExists(string url)
{
    bool result = true;

    WebRequest webRequest = WebRequest.Create(url);
    webRequest.Timeout = 1200; // miliseconds
    webRequest.Method = "HEAD";

    try
    {
        webRequest.GetResponse();
    }
    catch
    {
        result = false;
    }

    return result;
}
Mack
  • 2,556
  • 1
  • 26
  • 44
Kavit Trivedi
  • 129
  • 3
  • 13
4

If you are using a unc path or a mapped drive, this will work fine.

If you are using a web address (http, ftp etc) you are better off using WebClient - you will get a WebException if it doesn't exist.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
4
public static bool UrlExists(string file)
    {
        bool exists = false;
        HttpWebResponse response = null;
        var request = (HttpWebRequest)WebRequest.Create(file);
        request.Method = "HEAD";
        request.Timeout = 5000; // milliseconds
        request.AllowAutoRedirect = false;

        try
        {
            response = (HttpWebResponse)request.GetResponse();
            exists = response.StatusCode == HttpStatusCode.OK;
        }
        catch
        {
            exists = false;
        }
        finally
        {
            // close your response.
            if (response != null)
                response.Close();
        }
        return exists;
    }
LastEnd
  • 71
  • 3
  • Allows you to check webpage or any file located on a web server. Even if it tries to redirects to a 404 page. – LastEnd Aug 01 '14 at 21:56
3

I had the same problem to solve in asp.net core, I've solved with HttpClient

private async Task<bool> isFileExist(string url)
        {
            using (HttpClient client = new HttpClient())
            {
                var restponse = await client.GetAsync(url);

               return restponse.StatusCode == System.Net.HttpStatusCode.OK;
            }
        }
Mofaggol Hoshen
  • 686
  • 1
  • 7
  • 20
2

My version:

    public bool IsUrlExist(string url, int timeOutMs = 1000)
    {
        WebRequest webRequest = WebRequest.Create(url);
        webRequest.Method = "HEAD";
        webRequest.Timeout = timeOutMs;

        try
        {
            var response = webRequest.GetResponse();
            /* response is `200 OK` */
            response.Close();
        }
        catch
        {
            /* Any other response */
            return false;
        }

        return true;
    }
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
1

WebRequest will waiting long time(ignore the timeout user set) because not set proxy, so I change to use RestSharp to do this.

var client = new RestClient(url);
var request = new RestRequest(Method.HEAD);

 request.Timeout = 5000;
 var response = client.Execute(request);
 result = response.StatusCode == HttpStatusCode.OK;
nap
  • 41
  • 3
1

Thanks for all answers. And I would like to add my implementation which includes default state when we get errors, for specific cases like mine.

private bool HTTP_URLExists(String vstrURL, bool vResErrorDefault = false, int vTimeOut = 1200)
{
   bool vResult = false;
   WebRequest webRequest = WebRequest.Create(vstrURL);
   webRequest.Timeout = vTimeOut; // miliseconds
   webRequest.Method = "HEAD";
   HttpWebResponse response = null;
   try
   {
      response = (HttpWebResponse)webRequest.GetResponse();
      if (response.StatusCode == HttpStatusCode.OK) vResult = true;
      else if (response.StatusCode == HttpStatusCode.NotFound) vResult = false;
      else vResult = vResErrorDefault;
   }
       catch (WebException ex)
           {
           
              if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
              {
                  var resp01 = (HttpWebResponse)ex.Response;
                  if (resp01.StatusCode == HttpStatusCode.NotFound)
                  {
                      vResult = false;
                  }
                  else
                     {
                         vResult = vResErrorDefault;
                     }
                 }
                 else
                     {
                         vResult = vResErrorDefault;
                     }
                 }
           finally
           {
               // Don't forget to close your response.
               if (response != null)
               {
                   response.Close();
               }
           }
           return vResult;
}
0

Anoter version with define timeout :

public bool URLExists(string url,int timeout = 5000)
{
    ...
    webRequest.Timeout = timeout; // miliseconds
    ...
}
azouin
  • 19
  • 1
0

This works for me:

bool HaveFile(string url)
        {
            try
            {
                using (WebClient webClient = new WebClient())
                {
                    webClient.DownloadString(url);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }