•  

ГлавнаяIndyЧастые вопросы по Indy → Как организовать удаление, копирование и переименование не пустой директории на ftp-сервере

Создано: 24.05.2014 23:23:07 · Исправлено: 24.05.2014 23:23:07 · Прочтений: 997

Очень нужна ваша помощь. Как можно организовать удаление, копирование и переименование не пустой директории на ftp-сервере. Использую indy. Понимаю, что нужно использовать рекурсию. Даже нашел пару вариант как это реализовать, но не выходит - выскакивает ошибка CWD command not implemented.

Вот исходник клиента:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdFTP, IdBaseComponent, IdComponent, IdTCPConnection,
IdTCPClient, IdFTPList;

type
TForm1 = class(TForm)
Button1: TButton;
FTP: TIdFTP;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FTPConnected(Sender: TObject);
procedure Button2Click(Sender: TObject);
private

procedure DelFTPDir(Dir: String);

{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}



procedure TForm1.DelFTPDir(Dir: String);
var DL: TStringList;
L,FTPDL:TStringList;
i: integer;
begin
Application.ProcessMessages;
if FTP.Connected then
begin
DL:=TStringList.Create;
L:=TStringList.Create;
FTPDL:=TStringList.Create;
FTP.ChangeDir(Dir);
FTP.List(DL);
for i:=0 to DL.Count-1 do
begin
FTPDL.Add(FTP.DirectoryListing[i].FileName);
if FTP.DirectoryListing[i].ItemType = ditDirectory then
L.Add(d) else
L.Add(f);
end;
for i:=DL.Count-1 downto 0 do
begin
if (L[i]=d) then
begin
if (FTPDL[i]<> .) and
(FTPDL[i]<> ..) then
begin
DelFTPDir(FTPDL[i]);
end;
end
else
begin
FTP.Delete(FTPDL[i]);
end;
end;
FTP.ChangeDirUp;
FTP.RemoveDir(Dir);
FTPDL.Destroy;
DL.Destroy;
L.Destroy;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
FTP.Connect;
end;

procedure TForm1.FTPConnected(Sender: TObject);
begin
caption:=con;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
DelFtpDir(\111);
end;

end.
Эти вопросы должны быть к FTP-серверу, поскольку команда эта предназначена для смены текущей директории(как CD в ДОС-е). Её конечно могли запретить на самом FTP сервере с целью пресечь возможность получения списка всех папок и их структуры.
Моим эксперементом был и такой подход:

на клиенте ftp.RemoveDir(c:\222);

на сервере использую функцию:
function FullRemoveDir(Dir: string; DeleteAllFilesAndFolders,
  StopIfNotAllDeleted, RemoveRoot: boolean): Boolean;
var
  i: Integer;
  SRec: TSearchRec;
  FN: string;
begin
  Result := False;
  if not DirectoryExists(Dir) then
    exit;
  Result := True;
  // Добавляем слэш в конце и задаем маску - все файлы и директории
  Dir := IncludeTrailingBackslash(Dir);
  i := FindFirst(Dir + *, faAnyFile, SRec);
  try
    while i = 0 do
    begin
      // Получаем полный путь к файлу или директорию
      FN := Dir + SRec.Name;
      // Если это директория
      if SRec.Attr = faDirectory then
      begin
        // Рекурсивный вызов этой же функции с ключом удаления корня
        if (SRec.Name <> ) and (SRec.Name <> .) and (SRec.Name <> ..) then
        begin
          if DeleteAllFilesAndFolders then
            FileSetAttr(FN, faArchive);
          Result := FullRemoveDir(FN, DeleteAllFilesAndFolders,
            StopIfNotAllDeleted, True);
          if not Result and StopIfNotAllDeleted then
            exit;
        end;
      end
      else // Иначе удаляем файл
      begin
        if DeleteAllFilesAndFolders then
          FileSetAttr(FN, faArchive);
        Result := SysUtils.DeleteFile(FN);
        if not Result and StopIfNotAllDeleted then
          exit;
      end;
      // Берем следующий файл или директорию
      i := FindNext(SRec);
    end;
  finally
    SysUtils.FindClose(SRec);
  end;
  if not Result then
    exit;
  if RemoveRoot then // Если необходимо удалить корень - удаляем
    if not RemoveDir(Dir) then
      Result := false;
end;

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