2008-09-23 5 views

Répondre

27

Quelques considérations importantes avant le code:

  1. Le serveur HTTP doit être configuré pour permettre liste de répertoires pour les répertoires que vous souhaitez;
  2. Étant donné que les listes de répertoires sont des pages HTML normales, aucune norme ne définit le format d'une liste de répertoires;
  3. En raison de considération vous êtes dans le pays où vous devez mettre un code spécifique pour chaque serveur.

Mon choix consiste à utiliser des expressions régulières. Cela permet une analyse et une personnalisation rapides. Vous pouvez obtenir un modèle d'expressions régulières spécifique par site et ainsi vous avez une approche très modulaire. Utilisez une source externe pour mapper l'URL aux modèles d'expressions régulières si vous envisagez d'améliorer le module d'analyse avec la prise en charge des nouveaux sites sans modifier le code source.

Exemple pour imprimer la liste des répertoires de 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(); 
     } 
    } 
} 
8

Connaissances de base:

listes de répertoires ne sont que des pages HTML générées par un serveur Web. Chaque serveur Web génère ces pages HTML à sa guise, car il n'existe aucun moyen standard pour qu'un serveur Web lise ces répertoires. La meilleure façon d'obtenir une liste de répertoires est de simplement faire une requête HTTP à l'URL pour laquelle vous souhaitez que le répertoire apparaisse et d'essayer d'analyser et d'extraire tous les liens du code HTML qui vous est retourné. Pour analyser les liens HTML, essayez d'utiliser le HTML Agility Pack.

Parcourir le répertoire:

Le serveur Web que vous souhaitez vous à la liste des répertoires à partir doit avoir la navigation répertoire activé pour obtenir cette représentation HTML des fichiers dans ses répertoires. Vous ne pouvez donc obtenir la liste du répertoire que si le serveur HTTP veut que vous le puissiez.

Un exemple rapide du HTML Agilité pack:

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

Cleaner alternatif:

S'il est possible dans votre situation, une méthode plus propre est d'utiliser un protocole prévu pour le répertoire listes, comme le protocole de transfert de fichiers (FTP), SFTP (FTP comme sur SSH) ou FTPS (FTP sur SSL).

si la navigation du répertoire n'est pas activée:

Si le serveur Web n'a pas la navigation répertoire activée, alors il n'y a pas moyen facile d'obtenir la liste des répertoires. Le mieux que vous puissiez faire dans ce cas est de commencer à une URL donnée, de suivre tous les liens HTML sur la même page et d'essayer de créer une liste virtuelle de répertoires en vous basant sur les chemins relatifs des ressources sur ces pages HTML. pages Cela ne vous donnera pas une liste complète de ce que les fichiers sont réellement sur le serveur web.

0

Vous ne pouvez pas, à moins que le répertoire particulier que vous voulez ait une liste de répertoires activée et aucun fichier par défaut (généralement index.htm, index.html ou default.html mais toujours configurable). Ce n'est qu'alors que vous serez présenté avec une liste de répertoires, qui seront généralement balisés avec HTML et nécessitent une analyse syntaxique.

0

Vous pouvez également définir le serveur pour WebDAV.

2

Merci pour le super article. pour moi, le motif ci-dessous a mieux fonctionné.

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

J'ai également testé à http://regexhero.net/tester.

pour l'utiliser dans votre code C#, vous devez ajouter plus antislashs() avant toute backslash et des guillemets doubles dans le modèle pour i

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

nstance, dans la méthode GetDirectoryListingRegexForUrl vous devriez utiliser quelque chose comme ceci

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

Cheers!

+0

Merci beaucoup. Il a gagné du temps. –

4

je viens modifié ci-dessus et a trouvé ce meilleur

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(); 
     } 
    } 
} 
1

Le code suivant fonctionne bien pour moi quand je n'ai pas accès au serveur 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(); 
} 

Toutefois, lorsque J'ai accès au serveur ftp, le code suivant fonctionne beaucoup plus rapidement:

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); 
} 
Questions connexes