14

我需要一个简短的代码片段来从 HTTP 服务器获取目录列表。

谢谢

4

7 回答 7

31

代码之前的一些重要注意事项:

  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();
        }
    }
}
于 2008-09-23T23:20:37.277 回答
9

基本理解:

目录列表只是由 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(FTP 类似通过 SSH)或 FTPS(FTP 通过 SSL)。

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

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

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

于 2008-09-23T23:09:51.983 回答
4

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

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();
        }
    }
}
于 2013-10-10T19:06:19.037 回答
3

当我无法访问 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);
}
于 2014-10-16T21:33:09.560 回答
2

谢谢你的好帖子。对我来说,下面的模式效果更好。

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

我还在http://regexhero.net/tester对其进行了测试。

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

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

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

返回 "< A HREF=\\"\S+\\">(?\S+)";

干杯!

于 2013-02-22T19:02:55.207 回答
0

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

于 2008-09-23T23:11:14.383 回答
0

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

于 2008-09-23T23:26:43.177 回答