Получение списка файлов с FTP-сервера в C#

Я пытаюсь получить список файлов с FTP-сервера, но получаю странные ответы, отличные от ASCII.

Вот код, который я использую:

 public string[] getFileList(string mask)
 {
   if(!logined)
   {
     login();
   }
   Socket cSocket = createDataSocket();
   this.getSslDataStream(cSocket);
   sendCommand("PASV");
   sendCommand("LIST " + "*"+mask);
   stream2.AuthenticateAsClient(remoteHost,
      null,
      System.Security.Authentication.SslProtocols.Ssl3 |
      System.Security.Authentication.SslProtocols.Tls,
      true);
   if(!(retValue == 150 || retValue == 125))
   {
     throw new IOException(reply.Substring(4));
   }
   StringBuilder mes = new StringBuilder();       
   while(true)
   {
     int bytes = cSocket.Receive(buffer, buffer.Length, 0);
     mes.Append(ASCII.GetString(buffer, 0, bytes));
     if(bytes < buffer.Length)
     {
       break;
     }
   }
   string[] seperator = {"\r\n"};
   string[] mess = mes.ToString().Split(seperator, StringSplitOptions.RemoveEmptyEntries);
   cSocket.Close();
   readReply();
   if(retValue != 226)
   {
     throw new IOException(reply.Substring(4));
   }
   return mess;
 }

Ответ, который я получаю от FTP-сервера, таков:

WRITE:PASV

READ:227 Entering Passive Mode (10,0,2,24,5,119)`

WRITE:LIST *.dat

READ:150 Opening ASCII mode data connection for /bin/ls.

READ:226 Transfer complete.

Это останавливается там. Возвращаемый массив строк содержит один индекс с некоторыми не-ASCII-символами. Выглядит как куча мусора. Возможно, моя часть ASCII.GetString неверна? Я не совсем уверен.

Заранее спасибо.


person Aaron    schedule 13.11.2009    source источник
comment
Какую версию .NET Framework вы используете?   -  person Kev    schedule 13.11.2009
comment
Просто комментарий ... Я могу правильно скачивать и загружать файлы. Список и возврат списка, кажется, единственное, что я не могу сделать. Я пробовал LS, LIST и NLST. LS по какой-то причине не распознается, и LIST и NLST делают то же самое.   -  person Aaron    schedule 13.11.2009


Ответы (3)


Я написал довольно простую в использовании библиотеку-оболочку для всего, что связано с FtpWebRequest. Если вы хотите проверить это, это здесь https://gist.github.com/1242616

Я использую его во многих производственных средах, и он меня еще не подводил.

person Community    schedule 16.11.2009

Что бы это ни стоило, пространство имен System.Net имеет FtpWebRequest и FtpWebResponse, начиная с .Net 2.0.

Вот некоторый код, который я использовал, который записывает файлы сервера в локальный файл:

...
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(address);
ftpRequest.Credentials = new NetworkCredential(username, password);
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
ftpRequest.KeepAlive = false;

FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();

sr = new StreamReader(ftpResponse.GetResponseStream());
sw = new StreamWriter(new FileStream(fileName, FileMode.Create));

sw.WriteLine(sr.ReadToEnd());
sw.Close();

ftpResponse.Close();
sr.Close();
...
person Austin Salonen    schedule 13.11.2009
comment
Я знаю. Я использую код, который был написан 2 года назад, но отлично работает для загрузки и скачивания в других программах. Я хотел бы использовать тот же код, если это возможно. - person Aaron; 13.11.2009
comment
Я бы не стал переписывать все это - просто перечислил файлы. - person Austin Salonen; 13.11.2009
comment
Ok. Я пробовал, но мой URI дает исключение неизвестного формата. Это должно быть просто имя моего ftp-сервера, верно? - person Aaron; 13.11.2009
comment
Он должен быть в форме ftp://url.com - person Austin Salonen; 13.11.2009

public Socket BuildDataConn(Socket FirstSocket)
{
    string ret = "";
    string RemoteIP = "";
    int RemotePort = 0;
    SendCommand("PASV");

    int id = 0;
    id = strMsg.LastIndexOf(')');
    if (id != 0) 
    {
        string tmp = strMsg.Substring(strMsg.LastIndexOf('(') + 1, id - strMsg.LastIndexOf('(') - 1);
        string[] bByte = tmp.Split(',');
        RemotePort = int.Parse(bByte[4]) * 256 + Byte.Parse(bByte[5]);
        RemoteIP = bByte[0]+"." + bByte[1] + "." + bByte[2] + "." + bByte[3];
    }
    Socket NewConn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPEndPoint RemoteIPPort = new IPEndPoint(IPAddress.Parse(RemoteIP), RemotePort);
    try
    {
        NewConn.Connect(RemoteIPPort);
    }
    catch
    {
        throw new IOException("unable to Connect  !");
    }
    return NewConn;
}

Вместо использования cSocket для получения данных ответа вам нужно получить второй сокет, а затем использовать сокет для получения данных ответа. второй сокет ответит на отправку информации. И убедитесь, что вы изменили свой рабочий каталог FTP, прежде чем отправлять команду LIST.

public List<string> GetFileNames()
{
    if (!bConnected)
    {
        Open();
    }
    List<string> retObj = new List<string>();
    Socket dataSock =  BuildDataConn(mySocket);

    SendCommand("NLST");
    string dataSockMsg = "";
    buffer = new byte[BLOCK_SIZE];

    while (true)
    {
        int iBytes = dataSock.Receive(buffer, buffer.Length, 0);
        dataSockMsg += System.Text.Encoding.ASCII.GetString(buffer, 0, iBytes);
        if (iBytes < buffer.Length)
        {
            break;
        }
    }

    string[] message = dataSockMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);     

    dataSock.Close();

    foreach (string obj in message)
    {
        retObj.Add(obj);
    }

    return retObj;
}
person Marshall    schedule 25.08.2015