Загрузите файл с именем, включая специальные символы, с FTP-сервера в C #

Я пытался скачать файлы, но все файлы со специальными символами не распознаются. Другие файлы могут быть загружены, а файл с именем asdf#[email protected] не может быть загружен.

Ошибка:

Удаленный сервер вернул ошибку: (550) Файл недоступен (например, файл не найден, нет доступа).

В локальной создается файл с правильным именем, но он пустой. То же самое происходит с файлами JPG с # внутри имен файлов. как я могу позволить им быть признанным?

//Download the file from remote path on FTP to local path
private static void Download(string remotePath, string localPath)
{
    FtpWebRequest reqFTP;
    try
    {
        reqFTP = GetWebRequest(WebRequestMethods.Ftp.DownloadFile, remotePath);
        FileStream outputStream = new FileStream(localPath, FileMode.Create);

        FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
        Stream ftpStream = response.GetResponseStream();
        long cl = response.ContentLength;
        int bufferSize = 2048;
        int readCount;
        byte[] buffer = new byte[bufferSize];
        readCount = ftpStream.Read(buffer, 0, bufferSize);
        while (readCount > 0)
        {
            outputStream.Write(buffer, 0, readCount);
            readCount = ftpStream.Read(buffer, 0, bufferSize);
        }
        ftpStream.Close();
        outputStream.Close();
        response.Close();
        Console.WriteLine("File Download: ", remotePath + " is downloaded completely");
        logWriter.WriteLog("File Download: ", remotePath + " is downloaded completely, status " + response.StatusDescription);
    }
    catch (Exception ex)
    {
        logWriter.WriteLog("File Download: ", "Cannot download file from " + remotePath + " to " + localPath + "\n" + " Erro Message: " + ex.Message);
    }
}//End Download

//Web request for FTP
static public FtpWebRequest GetWebRequest(string method, string uri)
{
    Uri serverUri = new Uri(uri);

    if (serverUri.Scheme != Uri.UriSchemeFtp)
    {
        return null;
    }
    try
    {
        var reqFTP = (FtpWebRequest)FtpWebRequest.Create(serverUri);
        reqFTP.Method = method;
        reqFTP.UseBinary = true;
        reqFTP.Credentials = new NetworkCredential(userId, password);
        reqFTP.Proxy = null;
        reqFTP.KeepAlive = false;
        reqFTP.UsePassive = false;
        return reqFTP;
    }
    catch(Exception ex)
    {
        logWriter.WriteLog("Get Web Request: ","Cannot connect to " + uri + "\n" + "Error: " + ex.Message);
        return null;
    }
}

person Quentin    schedule 23.07.2013    source источник
comment
Что вы имеете в виду под не может быть признан? Какая у вас ошибка? Каков результат, когда вы пытаетесь получить список каталогов этого FTP-каталога с помощью WebMethods.Ftp.ListDirectory?   -  person Heinzi    schedule 23.07.2013
comment
Другие файлы можно загрузить, а файл с именем asdf#[email protected] скачать нельзя. Ошибка: Удаленный сервер вернул ошибку: (550) Файл недоступен (например, файл не найден, нет доступа).   -  person Quentin    schedule 23.07.2013
comment
правильное имя файла в WebMethods.Ftp.ListDirectory.   -  person Quentin    schedule 23.07.2013
comment
@Quentin: веб-сервер выдает ошибку. Это не имеет ничего общего с этим кодом. Если вы владеете этим веб-сервером, вам следует начать изучать его. Я не знаю, каковы ограничения на имена для разных файловых систем, но я подозреваю, что проблема в том, что файловая система, в которой работает сервер, и/или файловая система, в которой работает код, не поддерживает файлы с этими символами в их имени.   -  person caesay    schedule 23.07.2013
comment
@caesay: я попробовал ftp-сервер в своей компании (в качестве теста) и один в гостевой компании. Ни один из двух не может скачать файл с #@. Я должен скачать файлы из гостевой компании. Как я могу это решить? Спасибо.   -  person Quentin    schedule 23.07.2013
comment
@Quentin: Можете ли вы загрузить файл с помощью другого FTP-клиента (то есть не вашей программы)?   -  person Heinzi    schedule 23.07.2013
comment
@Heinzi: извините за поздний ответ. Да. На самом деле, если я изменю файл на обычное имя, это сработает. Поэтому я почти уверен, что могу что-то сделать с именем файла или URI.   -  person Quentin    schedule 23.07.2013
comment
@Quentin: Мой вопрос был направлен на другое: если вы сохраните странное имя файла и используете обычный FTP-клиент (например, Internet Explorer или что-то еще), можете ли вы загрузить файл?   -  person Heinzi    schedule 23.07.2013
comment
@Heinzi: Да, IE и Filezilla могут правильно его загрузить.   -  person Quentin    schedule 23.07.2013


Ответы (2)


Это может быть преднамеренным: согласно стандарту URI, # не является допустимым символом в URI. Таким образом, ftp://someServer/somePath/intro_to_c#.pdf не является допустимым URI.

Что вы можете сделать, так это правильно экранировать имя файла при создании URI:

string baseUri = "ftp://someServer/somePath/";
string file = "intro_to_c#.pdf";
string myUri = baseUri + HttpUtility.UrlEncode(file);
// yields ftp://someServer/somePath/intro_to_c%23.pdf

В качестве альтернативы вы можете использовать класс UriBuilder, который правильно обрабатывает экранирование:

Uri myUri = new UriBuilder("ftp", "someServer", 21, "somePath/intro_to_c#.pdf");
// yields ftp://someServer:21/somePath/intro_to_c%23.pdf
person Heinzi    schedule 24.07.2013

Я добавляю код и исправляю его. Используйте hexEscape, чтобы экранировать "#", но это не прилично. У кого-нибудь есть идея избежать специальных символов в URI?

    // Get the request using a specific URI 
    static public FtpWebRequest GetWebRequest(string method, string uri)
    {
        Uri serverUri = new Uri(uri);

        **if (serverUri.ToString().Contains("#"))
        {
            serverUri = new Uri(serverUri.ToString().Replace("#", Uri.HexEscape('#')));
        }**
        Console.WriteLine(serverUri.ToString());
        if (serverUri.Scheme != Uri.UriSchemeFtp)
        {
            return null;
        }
        try
        {
            var reqFTP = (FtpWebRequest)FtpWebRequest.Create(serverUri);
            reqFTP.Method = method;
            reqFTP.UseBinary = true;
            reqFTP.Credentials = new NetworkCredential(userId, password);
            reqFTP.Proxy = null;
            reqFTP.KeepAlive = false;
            reqFTP.UsePassive = false;
            return reqFTP;
        }

        catch (Exception ex)
        {
            logWriter.WriteLog("Get Web Request: ", "Cannot connect to " + uri + "\n" + "Error: " + ex.Message);
            return null;
        }
    }
person Quentin    schedule 24.07.2013