Как я могу использовать FTP для перемещения файлов между каталогами? - PullRequest
18 голосов
/ 01 февраля 2011

У меня есть программа, которая должна переместить файл из одного каталога в другой на FTP-сервере.Например, файл находится в:

ftp://1.1.1.1/MAIN/Dir1

, и мне нужно переместить файл в:

ftp://1.1.1.1/MAIN/Dir2

Я нашел несколько статей, рекомендующих использовать команду Rename, поэтому япробовал следующее:

    Uri serverFile = new Uri(“ftp://1.1.1.1/MAIN/Dir1/MyFile.txt");
    FtpWebRequest reqFTP= (FtpWebRequest)FtpWebRequest.Create(serverFile);
    reqFTP.Method = WebRequestMethods.Ftp.Rename;
    reqFTP.UseBinary = true;
    reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
    reqFTP.RenameTo = “ftp://1.1.1.1/MAIN/Dir2/MyFile.txt";

    FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();

Но, похоже, это не работает - я получаю следующую ошибку:

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

Сначала я подумал, что это может быть связано с разрешениями, но, насколько я вижу, у меня есть разрешения на весь FTP-сайт (он находится на моемлокальный ПК, и URI преобразуется в localhost).

Можно ли перемещать файлы между каталогами, как это, и если нет, то как это возможно?

Для решения некоторых из пунктов/ предложения, которые были подняты:

  1. Я могу загрузить тот же файл из исходного каталога, так что он определенно существует (то, что я делаю, сначала скачивает файл, а затем перемещает его в другое место).
  2. Я могу получить доступ к FTP-сайту сбраузер (как исходный, так и целевой каталог)
  3. ftp-сервер работает под моим собственным экземпляром IIS на моем локальном компьютере.
  4. Путь и регистр указаны правильно и специальных символов нет.

Кроме того, я попытался установить путь к каталогу:

ftp://1.1.1.1/%2fMAIN/Dir1/MyFile.txt

Как для исходного, так и для целевого пути - но это также не имеет значения.

Я нашел эту статью, в которой, похоже, говорится, что указание пункта назначения в качестве относительного пути поможет - кажется невозможным указать абсолютный путь в качестве пункта назначения.

reqFTP.RenameTo = “../Dir2/MyFile.txt";

Ответы [ 9 ]

18 голосов
/ 13 сентября 2011

Возникла такая же проблема и нашел другой способ ее решения:

public string FtpRename( string source, string destination ) {
        if ( source == destination )
            return;

        Uri uriSource = new Uri( this.Hostname + "/" + source ), UriKind.Absolute );
        Uri uriDestination = new Uri( this.Hostname + "/" + destination ), UriKind.Absolute );

        // Do the files exist?
        if ( !FtpFileExists( uriSource.AbsolutePath ) ) {
            throw ( new FileNotFoundException( string.Format( "Source '{0}' not found!", uriSource.AbsolutePath ) ) );
        }

        if ( FtpFileExists( uriDestination.AbsolutePath ) ) {
            throw ( new ApplicationException( string.Format( "Target '{0}' already exists!", uriDestination.AbsolutePath ) ) );
        }

        Uri targetUriRelative = uriSource.MakeRelativeUri( uriDestination );


        //perform rename
        FtpWebRequest ftp = GetRequest( uriSource.AbsoluteUri );
        ftp.Method = WebRequestMethods.Ftp.Rename;
        ftp.RenameTo = Uri.UnescapeDataString( targetUriRelative.OriginalString );

        FtpWebResponse response = (FtpWebResponse)ftp.GetResponse(); 

        return response.StatusDescription; 

    }
12 голосов
/ 01 февраля 2011

MSDN , по-видимому, предполагает, что ваш путь считается относительным, и поэтому он пытается войти на FTP-сервер с использованием предоставленных учетных данных, а затем устанавливает текущий каталог на * Каталог 1005 *. Если это не тот каталог, где находится ваш файл, вы получите ошибку 550.

2 голосов
/ 03 марта 2016

В следующем примере кода я попытался со следующими данными, и это работает.

Адрес для входа на FTP - "C: \ FTP".

Исходное местоположение файла «C: \ FTP \ Data \ FTP.txt».

Файл, который нужно переместить, «C: \ FTP \ Move \ FTP.txt».

Uri serverFile = new Uri(“ftp://localhost/Data/FTP.txt");
FtpWebRequest reqFTP= (FtpWebRequest)FtpWebRequest.Create(serverFile);
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
reqFTP.RenameTo = “../Move/FTP.txt";

FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
1 голос
/ 19 августа 2011

Что делать, если у вас есть только абсолютные пути?

Хорошо, я наткнулся на этот пост, потому что я получил ту же ошибку.Похоже, что ответ заключается в использовании относительного пути, что не очень хорошо подходит для решения моей проблемы, поскольку пути к папкам я получаю в виде строк с абсолютным путем.

Решения, которые я нашел налетаю работать, но уродливо, если не сказать больше.Я сделаю это ответом сообщества вики, и если у кого-то есть лучшее решение, не стесняйтесь редактировать это.

С тех пор как я узнал об этом, у меня есть 2 решения.

  1. Возьмите абсолютный путь от перехода к пути и преобразуйте его в относительный URL.

    public static string GetRelativePath(string ftpBasePath, string ftpToPath)
    {
    
        if (!ftpBasePath.StartsWith("/"))
        {
            throw new Exception("Base path is not absolute");
        }
        else
        {
            ftpBasePath =  ftpBasePath.Substring(1);
        }
        if (ftpBasePath.EndsWith("/"))
        {
            ftpBasePath = ftpBasePath.Substring(0, ftpBasePath.Length - 1);
        }
    
        if (!ftpToPath.StartsWith("/"))
        {
            throw new Exception("Base path is not absolute");
        }
        else
        {
            ftpToPath = ftpToPath.Substring(1);
        }
        if (ftpToPath.EndsWith("/"))
        {
            ftpToPath = ftpToPath.Substring(0, ftpToPath.Length - 1);
        }
        string[] arrBasePath = ftpBasePath.Split("/".ToCharArray());
        string[] arrToPath = ftpToPath.Split("/".ToCharArray());
    
        int basePathCount = arrBasePath.Count();
        int levelChanged = basePathCount;
        for (int iIndex = 0; iIndex < basePathCount; iIndex++)
        {
            if (arrToPath.Count() > iIndex)
            {
                if (arrBasePath[iIndex] != arrToPath[iIndex])
                {
                    levelChanged = iIndex;
                    break;
                }
            }
        }
        int HowManyBack = basePathCount - levelChanged;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < HowManyBack; i++)
        {
            sb.Append("../");
        }
        for (int i = levelChanged; i < arrToPath.Count(); i++)
        {
            sb.Append(arrToPath[i]);
            sb.Append("/");
        }
    
        return sb.ToString();
    }
    
    public static string MoveFile(string ftpuri, string username, string password, string ftpfrompath, string ftptopath, string filename)
    {
        string retval = string.Empty;
    
        FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftpfrompath + filename);
        ftp.Method = WebRequestMethods.Ftp.Rename;
        ftp.Credentials = new NetworkCredential(username, password);
        ftp.UsePassive = true;
        ftp.RenameTo = GetRelativePath(ftpfrompath, ftptopath) + filename;
        Stream requestStream = ftp.GetRequestStream();
    
    
        FtpWebResponse ftpresponse = (FtpWebResponse)ftp.GetResponse();
    
        Stream responseStream = ftpresponse.GetResponseStream();
    
        StreamReader reader = new StreamReader(responseStream);
    
        return reader.ReadToEnd();
    }
    

или ...

  1. Загрузите файл по пути «ftp from», загрузите его в «ftp to»путь и удалите его из пути «ftp from».

    public static string SendFile(string ftpuri, string username, string password, string ftppath, string filename, byte[] datatosend)
    {
        if (ftppath.Substring(ftppath.Length - 1) != "/")
        {
            ftppath += "/";
        }
        FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftppath + filename);
        ftp.Method = WebRequestMethods.Ftp.UploadFile;
        ftp.Credentials = new NetworkCredential(username, password);
        ftp.UsePassive = true;
        ftp.ContentLength = datatosend.Length;
        Stream requestStream = ftp.GetRequestStream();
        requestStream.Write(datatosend, 0, datatosend.Length);
        requestStream.Close();
    
        FtpWebResponse ftpresponse = (FtpWebResponse)ftp.GetResponse();
    
        return ftpresponse.StatusDescription;
    }
    public static string DeleteFile(string ftpuri, string username, string password, string ftppath, string filename)
    {
    
        FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftppath + filename);
        ftp.Method = WebRequestMethods.Ftp.DeleteFile;
        ftp.Credentials = new NetworkCredential(username, password);
        ftp.UsePassive = true;
    
        FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
    
        Stream responseStream = response.GetResponseStream();
    
        StreamReader reader = new StreamReader(responseStream);
    
        return reader.ReadToEnd();
    }
    public static string MoveFile(string ftpuri, string username, string password, string ftpfrompath, string ftptopath, string filename)
    {
        string retval = string.Empty;
        byte[] filecontents = GetFile(ftpuri, username, password, ftpfrompath, filename);
        retval += SendFile(ftpuri, username, password, ftptopath, filename, filecontents);
        retval += DeleteFile(ftpuri, username, password, ftpfrompath, filename);
        return retval;
    }
    
1 голос
/ 11 апреля 2011

Мне удалось заставить это работать, но только с использованием пути, существующего на сервере, т.е. /DRIVELETTER:/FOLDERNAME/filename в RenameTo = "

0 голосов
/ 04 сентября 2018

U может использовать этот код:

Исходное местоположение файла " ftp: //example.com/directory1/Somefile.file".

Файл для перемещения, "/newDirectory/Somefile.file".

Обратите внимание, что URL назначения не нужно начинать с: ftp: //example.com

NetworkCredential User = new NetworkCredential("UserName", "password");
FtpWebRequest Wr =FtpWebRequest)FtpWebRequest.Create("ftp://Somwhere.com/somedirectory/Somefile.file");
Wr.UseBinary = true;
Wr.Method = WebRequestMethods.Ftp.Rename;
Wr.Credentials = User;
Wr.RenameTo = "/someotherDirectory/Somefile.file";
back = (FtpWebResponse)Wr.GetResponse();
bool Success = back.StatusCode == FtpStatusCode.CommandOK || back.StatusCode == FtpStatusCode.FileActionOK;
0 голосов
/ 07 февраля 2012

Я работаю над проектом идентичного типа, попробуйте создать веб-сервис, который может перемещать файлы и запускаться на сервере, где находятся ваши файлы.Создайте его с параметром для передачи имени файла.При начале записи файла вам может понадобиться добавить значение к имени файла, например, PK данных, которые соответствуют файлу и т. Д.

0 голосов
/ 01 февраля 2011

Код выглядит правильно. Так что либо у вас неправильный путь, файл НЕ СУЩЕСТВУЕТ, либо вам нужно учитывать регистр (очевидно, Windows не учитывает регистр, но Linux, Unix это так).

Вы пытались открыть файл в браузере? Откройте проводник Windows, введите адрес в строке пути и посмотрите, что вы получите.

0 голосов
/ 01 февраля 2011

У вас есть эти папки, определенные в службе FTP?Служба FTP работает?Если ответ на любой вопрос - нет, вы не можете использовать FTP для перемещения файлов.

Попробуйте открыть папку FTP в клиенте FTP и посмотрите, что произойдет.Если у вас все еще есть ошибка, в вашем определении что-то не так, поскольку служба FTP не видит папку или папка не логически находится там, где вы думаете, что она находится в службе FTP.

Вы также можете открытьДиспетчер IIS и посмотрите, как все настроено в FTP.

Что касается других методов перемещения файлов, вы можете легко переходить с пути UNC на другой, если учетная запись, под которой запускается программа, имеет соответствующие разрешения для обоих.Путь UNC аналогичен пути HTTP или FTP, с ударами в противоположном направлении и без указания протокола.

...