【问题标题】:How do I check a WebClient Request for a 404 error如何检查 WebClient 请求中的 404 错误
【发布时间】:2012-01-23 08:06:40
【问题描述】:

我正在编写一个下载到文件的程序。第二个文件不是必需的,只是在某些时候被包括在内。如果不包含第二个文件,它将返回 HTTP 404 错误。

现在,问题是当返回此错误时,它会结束整个程序。我想要的是继续程序并忽略 HTTP 错误。所以,我的问题是如何从WebClient.DownloadFile 请求中捕获HTTP 404 错误?

这是当前使用的代码::

WebClient downloader = new WebClient();
foreach (string[] i in textList)
{
    String[] fileInfo = i;
    string videoName = fileInfo[0];
    string videoDesc = fileInfo[1];
    string videoAddress = fileInfo[2];
    string imgAddress = fileInfo[3];
    string source = fileInfo[5];
    string folder = folderBuilder(path, videoName);
    string infoFile = folder + '\\' + removeFileType(retrieveFileName(videoAddress)) + @".txt";
    string videoPath = folder + '\\' + retrieveFileName(videoAddress);
    string imgPath = folder + '\\' + retrieveFileName(imgAddress);
    System.IO.Directory.CreateDirectory(folder);
    buildInfo(videoName, videoDesc, source, infoFile);
    textBox1.Text = textBox1.Text + @"begining download of files for" + videoName;
    downloader.DownloadFile(videoAddress, videoPath);
    textBox1.Text = textBox1.Text + @"Complete video for" + videoName;
    downloader.DownloadFile(imgAddress, imgPath);
    textBox1.Text = textBox1.Text + @"Complete img for" + videoName;
}

【问题讨论】:

    标签: c# webclient


    【解决方案1】:

    如果您特别地想要捕获错误 404:

    using (var client = new WebClient())
    {
      try
      {
        client.DownloadFile(url, destination);
      }
      catch (WebException wex)
      {
        if (((HttpWebResponse) wex.Response).StatusCode == HttpStatusCode.NotFound)
        {
          // error 404, do what you need to do
        }
      }
    }
    

    或者,使用 C# 7 或更高版本:

    using (var client = new WebClient())
    {
      try
      {
        client.DownloadFile(url, destination);
      }
      catch (WebException ex) when
            (ex.Response is HttpWebResponse wr && wr.StatusCode == HttpStatusCode.NotFound)
      {      
        // error 404, do what you need to do
      }
    }
    

    【讨论】:

    • 这应该是公认的答案。获得一个实际的HttpWebResponse.StatusCodeenum 值比在string 消息中查找代码要好得多:-)
    • wex.Response 为空...不要在没有先测试的情况下写答案...
    【解决方案2】:

    WebClient will throw a WebException 用于所有 4xx 和 5xx 响应。

    try {
        downloader.DownloadFile(videoAddress, videoPath);
    }
    catch (WebException ex) {
        // handle it here
    }
    

    【讨论】:

      【解决方案3】:

      try catch 放入您的foreach 循环中。

       foreach (string[] i in textList)
       {
          try
          {
              String[] fileInfo = i;
              string videoName = fileInfo[0];
              string videoDesc = fileInfo[1];
              string videoAddress = fileInfo[2];
              string imgAddress = fileInfo[3];
              string source = fileInfo[5];
              string folder = folderBuilder(path, videoName);
              string infoFile = folder + '\\' + removeFileType(retrieveFileName(videoAddress)) + @".txt";
              string videoPath = folder + '\\' + retrieveFileName(videoAddress);
              string imgPath = folder + '\\' + retrieveFileName(imgAddress);
              System.IO.Directory.CreateDirectory(folder);
              buildInfo(videoName, videoDesc, source, infoFile);
              textBox1.Text = textBox1.Text + @"begining download of files for" + videoName;
              if(Download(videoAddress, videoPath) == false)
              {
                 //Download failed. Do what you want to do.
              }
              textBox1.Text = textBox1.Text + @"Complete video for" + videoName;
              if(Download(imgAddress, imgPath)== false)
              {
                 //Download failed. Do what you want to do.
              }
              textBox1.Text = textBox1.Text + @"Complete img for" + videoName;
          }
          catch(Exception ex)
          {
              //Error like IO Exceptions, Security Errors can be handle here. You can log it if you want.
          }
       }
      

      下载文件的私有函数

       private bool Download(string url, string destination)
       {
           try
           {
               WebClient downloader = new WebClient();
               downloader.DownloadFile(url, destination);
               return true;
           }
           catch(WebException webEx)
           {
              //Check (HttpWebResponse)webEx.Response).StatusCode
              // Or
              //Check for webEx.Status
           }
           return false;
       }
      

      您可以查看WebException 的状态。根据错误代码,您可以继续或中断。

      阅读更多@MSDN

      建议

      希望这对你有用。

      【讨论】:

      • 这种结构的方式你将无法判断对 DownloadFile 的哪些调用导致了异常,并且捕获 Exception 是不必要的。
      • 堆栈跟踪可以让您知道哪个下载失败。无论如何更新了答案。
      【解决方案4】:

      您可以尝试使用此代码从 WebException 或 OpenReadCompletedEventArgs.Error 获取 HTTP 状态代码:

      HttpStatusCode GetHttpStatusCode(System.Exception err)
      {
          if (err is WebException)
          {
              WebException we = (WebException)err;
              if (we.Response is HttpWebResponse)
              {
                  HttpWebResponse response = (HttpWebResponse)we.Response;
                  return response.StatusCode;
              }
          }
          return 0;
      }
      

      【讨论】:

        【解决方案5】:

        在您的代码中使用 try catch WebException 并检查 Exception 消息 - 它将包含 http StatusCode

        您可以清除Exception 并继续。

        【讨论】:

        • 捕获异常后如何清除异常并让程序继续运行?对不起,如果这看起来很新,但我是新手。
        • 试试 { downloader.DownloadFile(videoAddress, videoPath); catch (WebException ex) { // 在此处处理 // 通过在此处清除代码,不处理异常并且该过程可以继续:) }
        • 这似乎不起作用。如果文件不存在,则 API 正在下载 HTML 404 错误页面作为文件。
        【解决方案6】:

        在循环中使用带有 WebException 的 try{} catch{} 块! 不知道你使用的是什么 IDE,但使用 Visual Studio,你可以获得很多关于异常的信息 :)

        【讨论】:

          【解决方案7】:

          重要提示:在 404 失败时,DownloadFileTaskAsync 会抛出异常,但也会创建一个空文件。这至少可以说是令人困惑的!

          我花了很长时间才意识到除了抛出异常之外,这段代码还会创建一个空文件:

          await webClient.DownloadFileTaskAsync(new Uri("http://example.com/fake.jpg"), filename);
          

          我改用了这个(DownloadDataTaskAsync 而不是File):

           var data = await webClient.DownloadDataTaskAsync(new Uri("http://example.com/fake.jpg"));
           File.WriteAllBytes(filename, data);
          

          *我不确定 500 的行为,但可以肯定的是 404 会这样做。

          【讨论】:

            【解决方案8】:

            就像其他人写的那样,try-catch 就足够了。

            另一个技巧是使用HTTP HEAD 来检查那里是否有任何东西(它比执行完整的 HTTP GET 更轻松):

            var url = "url to check";
            var req = HttpWebRequest.Create(url);
            req.Method = "HEAD"; //this is what makes it a "HEAD" request
            WebResponse res = null;
            try
            {
                res = req.GetResponse();
                res.Close();
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                if (res != null)
                    res.Close();
            }
            

            【讨论】:

              【解决方案9】:

              我会这样用。

                  public void Test()
                  {
                      try
                      {
                          WebClient webClient = new WebClient();
                          webClient.DownloadString("");
                      }
                      catch (WebException webException)
                      {
                          if (int.TryParse(
                              Regex.Match(webException.Message, @"(?<=error:\s\()\d+(?=\))", RegexOptions.Multiline).Value,
                              out var result))
                          {
                              switch (result)
                              {
                                  case 404:
                                      Console.WriteLine("Error 404");
                                      break;
                                  case 500:
                                      Console.WriteLine("Error 500");
                                      break;
                              }
                          }
                      }
                  }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-09-02
                • 2013-01-29
                • 2016-05-18
                • 1970-01-01
                • 2019-11-22
                • 2015-07-31
                • 2021-07-31
                • 2017-12-11
                相关资源
                最近更新 更多