【问题标题】:C# HttpWebRequest command to get directory listing [closed]C# HttpWebRequest 命令获取目录列表[关闭]
【发布时间】:2010-09-12 13:48:37
【问题描述】:

我需要一个短代码 sn-p 从 HTTP 服务器获取目录列表。

谢谢

【问题讨论】:

    标签: c# http


    【解决方案1】:

    基本理解:

    目录列表只是由 Web 服务器生成的 HTML 页面。 每个 Web 服务器都以自己的方式生成这些 HTML 页面,因为 Web 服务器没有列出这些目录的标准方法。

    获取目录列表的最佳方法是简单地向您想要目录列表的 URL 发出 HTTP 请求,并尝试从返回给您的 HTML 中解析和提取所有链接。

    要解析 HTML 链接,请尝试使用HTML Agility Pack

    目录浏览:

    您要从中列出目录的 Web 服务器必须打开目录浏览功能,才能获取其目录中文件的 HTML 表示形式。因此,只有 HTTP 服务器希望您能够获得目录列表,您才能获得。

    HTML 敏捷包的简单示例:

    HtmlDocument doc = new HtmlDocument();
    doc.Load(strURL);
    foreach(HtmlNode link in doc.DocumentElement.SelectNodes("//a@href")
    {
    HtmlAttribute att = link"href";
    //do something with att.Value;
    }
    

    更清洁的替代品:

    如果可能在您的情况下,更简洁的方法是对目录列表使用预期的协议,例如文件传输协议 (FTP)、SFTP(通过 SSH 的 FTP)或 FTPS(通过 SSL 的 FTP)。

    如果目录浏览没有打开怎么办:

    如果网络服务器没有打开目录浏览,那么就没有简单的方法来获取目录列表。

    在这种情况下,您可以做的最好的事情是从给定的 URL 开始,跟踪同一页面上的所有 HTML 链接,并尝试根据这些 HTML 页面上资源的相对路径自己构建目录的虚拟列表.但是,这不会为您提供 Web 服务器上实际文件的完整列表。

    【讨论】:

      【解决方案2】:

      当我无法访问 ftp 服务器时,以下代码非常适合我:

      public static string[] GetFiles(string url)
      {
          List<string> files = new List<string>(500);
          HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
          using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
          {
              using (StreamReader reader = new StreamReader(response.GetResponseStream()))
              {
                  string html = reader.ReadToEnd();
      
                  Regex regex = new Regex("<a href=\".*\">(?<name>.*)</a>");
                  MatchCollection matches = regex.Matches(html);
      
                  if (matches.Count > 0)
                  {
                      foreach (Match match in matches)
                      {
                          if (match.Success)
                          {
                              string[] matchData = match.Groups[0].ToString().Split('\"');
                              files.Add(matchData[1]);
                          }
                      }
                  }
              }
          }
          return files.ToArray();
      }
      

      但是,当我确实可以访问 ftp 服务器时,以下代码运行得更快:

      public static string[] getFtpFolderItems(string ftpURL)
      {
          FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpURL);
          request.Method = WebRequestMethods.Ftp.ListDirectory;
      
          //You could add Credentials, if needed 
          //request.Credentials = new NetworkCredential("anonymous", "password");
      
          FtpWebResponse response = (FtpWebResponse)request.GetResponse();
      
          Stream responseStream = response.GetResponseStream();
          StreamReader reader = new StreamReader(responseStream);
      
          return reader.ReadToEnd().Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
      }
      

      【讨论】:

        【解决方案3】:

        我刚刚在上面进行了修改,发现这个最好

        public static class  GetallFilesFromHttp
        {
            public static string GetDirectoryListingRegexForUrl(string url)
            {
                if (url.Equals("http://ServerDirPath/"))
                {
                    return "\\\"([^\"]*)\\\""; 
                }
                throw new NotSupportedException();
            }
            public static void ListDiractory()
            {
                string url = "http://ServerDirPath/";
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        string html = reader.ReadToEnd();
        
                        Regex regex = new Regex(GetDirectoryListingRegexForUrl(url));
                        MatchCollection matches = regex.Matches(html);
                        if (matches.Count > 0)
                        {
                            foreach (Match match in matches)
                            {
                                if (match.Success)
                                {
                                    Console.WriteLine(match.ToString());
                                }
                            }
                        }
                    }
                    Console.ReadLine();
                }
            }
        }
        

        【讨论】:

          【解决方案4】:

          感谢您的精彩帖子。对我来说,下面的模式效果更好。

          <AHREF=\\"\S+\">(?<name>\S+)</A>
          

          我还在 http://regexhero.net/tester 上测试过。

          要在您的 C# 代码中使用它,您必须在 i 模式中的任何反斜杠和双引号之前添加更多反斜杠 ()

          &lt;AHREF=\\"\S+\"&gt;(?&lt;name&gt;\S+)&lt;/A&gt;

          例如,在 GetDirectoryListingRegexForUrl 方法中,您应该使用类似这样的方法

          返回 "(?\S+)";

          干杯!

          【讨论】:

          • 非常感谢。它节省了时间。
          【解决方案5】:

          您也可以将服务器设置为WebDAV

          【讨论】:

            【解决方案6】:

            代码前的几个重要注意事项:

            1. 必须将 HTTP 服务器配置为允许列出所需目录的目录;
            2. 因为目录列表是普通的 HTML 页面,所以没有定义目录列表格式的标准;
            3. 出于考虑2,您必须为每个服务器放置特定代码。

            我的选择是使用正则表达式。这允许快速解析和定制。您可以为每个站点获取特定的正则表达式模式,这样您就有了一种非常模块化的方法。如果您打算在不更改源代码的情况下通过新站点支持增强解析模块,请使用外部源将 URL 映射到正则表达式模式。

            http://www.ibiblio.org/pub/打印目录列表的示例

            namespace Example
            {
                using System;
                using System.Net;
                using System.IO;
                using System.Text.RegularExpressions;
            
                public class MyExample
                {
                    public static string GetDirectoryListingRegexForUrl(string url)
                    {
                        if (url.Equals("http://www.ibiblio.org/pub/"))
                        {
                            return "<a href=\".*\">(?<name>.*)</a>";
                        }
                        throw new NotSupportedException();
                    }
                    public static void Main(String[] args)
                    {
                        string url = "http://www.ibiblio.org/pub/";
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                        using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                        {
                            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                            {
                                string html = reader.ReadToEnd();
                                Regex regex = new Regex(GetDirectoryListingRegexForUrl(url));
                                MatchCollection matches = regex.Matches(html);
                                if (matches.Count > 0)
                                {
                                    foreach (Match match in matches)
                                    {
                                        if (match.Success)
                                        {
                                            Console.WriteLine(match.Groups["name"]);
                                        }
                                    }
                                }
                            }
                        }
            
                        Console.ReadLine();
                    }
                }
            }
            

            【讨论】:

              【解决方案7】:

              你不能,除非你想要的特定目录启用了目录列表并且没有默认文件(通常是 index.htm、index.html 或 default.html,但总是可配置的)。只有这样,您才会看到一个目录列表,通常会用 HTML 标记并需要解析。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-01-20
                • 1970-01-01
                • 2014-11-17
                • 2016-12-18
                • 2018-09-07
                • 2016-05-06
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多