Как собрать все файлы из определенной директории и всех её поддиректорий?
Вариант 1
Соберем имена файлов, кроме папок из определенной директории на FTP сервере при помощи компонента idFTP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
//Recursive listing of files... procedure TVisualFrame_PSFTPClient.ListAllFilesCore(dir:string); var DL: TStringList; i: Integer; begin DL:=TStringList.Create; try IdFTP.ChangeDir(Dir); IdFTP.List(DL, '', false); // <<<Listed all files and folders here... for i:=0 to DL.Count-1 do begin if IdFTP.Size(dl.Strings[i])=-1 then // If Folder then... ListAllFilesCore(dl.Strings[i]) //Recursion here... else FFilesOnServerAll.Add(DL.Strings[i]); end; IdFTP.ChangeDirUp; IdFTP.List(DL, '', false); // << Critical important !!! finally FreeAndNil(DL); end; end; |
И вторая процедура, которая собственно подключается к серверу и собирает файлы…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
//------------Список файлов с сервера всех директорий procedure TVisualFrame_PSFTPClient.ListAllFiles; begin with idFTP do begin Host:=FTPConnectionParams.Host;// 'localhost'; //FTP-сервер Port:=FTPConnectionParams.Port;// 22; //порт ФТП сервера Username:=FTPConnectionParams.Username;// 'Логин'; Password:=FTPConnectionParams.Password;// 'Пароль'; end; try idFTP.Connect; try try if IdFTP.Connected then begin // MAIN WORK HERE... ListAllFilesCore(FInitialDir); end; finally idFTP.Disconnect; end; except //Other exceptions on E: EIdException do begin showmessage(E.ClassName+' An network error occurred during communication: ' +#13#10+#13#10+E.Message); end; on E: Exception do begin showmessage(E.ClassName+' An unknown error occurred during communication: ' +#13#10+#13#10+E.Message); end; end; except // Catching Connection Exceptions on E: EIdException do begin showmessage(E.ClassName+' An network error occurred while trying to connect: ' +#13#10+#13#10+E.Message); StatusBar.Panels[1].Text:='FTP Connection '+E.Message; end; on E: Exception do begin showmessage(E.ClassName+'An unknown error occurred while trying to connect: ' +#13#10+#13#10+E.Message); end; end; end; |
Вариант 2
Если кроме имен файлов нужны размеры, даты создания, модификации и др., тогда делаем следующее
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
//Recursive listing of files... procedure TVisualFrame_PSFTPClient.ListAllFilesCore(dir:string); var i: Integer; FileSizeString: string; FileSize:Int64; Link: string; M: TMatchCollection; j,k: integer; M2:TMatchCollection; RegEx:TRegEx; begin FUpperDir:=IdFTP.RetrieveCurrentDir; IdFTP.ChangeDir(Dir); pAddress.Hide; IdFTP.List; // Listing All Files Here... for i := 0 to IdFTP.DirectoryListing.Count-1 do begin //if (IdFTP.Size(IdFTP.DirectoryListing[i].FileName)=-1) // means Folder if (IdFTP.DirectoryListing[i].ItemType=ditDirectory) and (IdFTP.DirectoryListing[i].FileName<>'.') and (IdFTP.DirectoryListing[i].FileName<>'..') and not (IdFTP.DirectoryListing[i].FileName.Contains('thumb')) then begin FDirs.Add(IdFTP.RetrieveCurrentDir+'/'+IdFTP.DirectoryListing[i].FileName); ListAllFilesCore(IdFTP.RetrieveCurrentDir+'/'+IdFTP.DirectoryListing[i].FileName); end else if (IdFTP.DirectoryListing[i].ItemType=ditFile) and (IdFTP.DirectoryListing[i].FileName<>'.') and (IdFTP.DirectoryListing[i].FileName<>'..') and not (IdFTP.DirectoryListing[i].FileName.Contains('thumb')) then begin // Adding ID FIDFile.Add(i.ToString); //Adding FileName FFilesOnServerAll.Add(IdFTP.DirectoryListing[i].FileName); //Getting FileSize FileSizeString:=GetFileSizeOnFTPServer(IdFTP.DirectoryListing[i].FileName,FileSize); //Adding FileSizeString FFileSizeListStringAll.Add( FileSizeString ); //Adding FileSizeBytes FFileSizeListBytesAll.Add(FileSize.ToString); // Links FLinksListAll.Add(IdFTP.RetrieveCurrentDir+'/'+IdFTP.DirectoryListing[i].FileName); // FFullDir:=FInitialDir+'/'+dir; // Add CreationDateTimeOnServerAll M:=RegEx.Matches(IdFTP.ListResult[i],'create=[\d]*[\d]\b'); for j := 0 to M.Count-1 do begin M2:=RegEx.Matches(M.Item[j].Value,'[\d]*[\d]\b'); for k := 0 to M2.Count-1 do begin FCreationDateTimeOnServerAll.Add( IndyStringToLocalizeDateTimeString( M2.Item[j].Value ) ); end; end; // Add ModifiedDateTimeOnServer... M:=RegEx.Matches(IdFTP.ListResult[i],'modify=[\d]*[\d]\b'); for j := 0 to M.Count-1 do begin M2:=RegEx.Matches(M.Item[j].Value,'[\d]*[\d]\b'); for k := 0 to M2.Count-1 do begin FModifiedDateTimeOnServerAll.Add( IndyStringToLocalizeDateTimeString( M2.Item[j].Value ) ); end; end; // Add LastAccessTime M:=RegEx.Matches(IdFTP.ListResult[i],'lastaccesstime=[\d]*[\d]\b'); for j := 0 to M.Count-1 do begin M2:=RegEx.Matches(M.Item[j].Value,'[\d]*[\d]\b'); for k := 0 to M2.Count-1 do begin FlastAccessTimeAll.Add( IndyStringToLocalizeDateTimeString( M2.Item[j].Value ) ); end; end; end; end; // for... IdFTP.ChangeDirUp; IdFTP.List; // <<< Critical Important !!! end; |
И собственно процедура, связывающая нас с сервером
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
//------------Список файлов с сервера всех директорий procedure TVisualFrame_PSFTPClient.ListAllFiles; begin with idFTP do begin Host:=FTPConnectionParams.Host;// 'localhost'; //FTP-сервер Port:=FTPConnectionParams.Port;// 22; //порт ФТП сервера Username:=FTPConnectionParams.Username;// 'Логин'; Password:=FTPConnectionParams.Password;// 'Пароль'; end; try idFTP.Connect; try try if IdFTP.Connected then begin // MAIN WORK HERE... //ClearingStringLists... FIDFile.Clear; FFilesOnServerAll.Clear; FFileSizeListStringAll.Clear; FFileSizeListBytesAll.Clear; FLinksListAll.Clear; FCreationDateTimeOnServerAll.Clear; FModifiedDateTimeOnServerAll.Clear; FlastAccessTimeAll.Clear; ListAllFilesCore(FInitialDir); end; finally idFTP.Disconnect; end; except //Other exceptions on E: EIdException do begin showmessage(E.ClassName+' An network error occurred during communication: ' +#13#10+#13#10+E.Message); end; on E: Exception do begin showmessage(E.ClassName+' An unknown error occurred during communication: ' +#13#10+#13#10+E.Message); end; end; except // Catching Connection Exceptions on E: EIdException do begin showmessage(E.ClassName+' An network error occurred while trying to connect: ' +#13#10+#13#10+E.Message); StatusBar.Panels[1].Text:='FTP Connection '+E.Message; end; on E: Exception do begin showmessage(E.ClassName+'An unknown error occurred while trying to connect: ' +#13#10+#13#10+E.Message); end; end; end; |
В результате, в стринглистах получим интересующую нас информацию.
Также понадобилась самописная функция по преобразованию строки Indy даты и времени, в “нормальную”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
function TVisualFrame_PSFTPClient.IndyStringToLocalizeDateTimeString(IndyString:string):string; var FFileTimeLocalized:TFileTime; FFileTime:TFileTime; SystemTimeLocalized:TSystemtime; SystemTime:TSystemtime; datetime: TDateTime; begin //if IndyString='' then begin // Result:=''; Exit; //end; //IndyString:='20160912210450'; // <<Example datetime := EncodeDateTime(StrToInt(Copy(IndyString, 1, 4)), StrToInt(Copy(IndyString, 5, 2)), StrToInt(Copy(IndyString, 7, 2)), StrToInt(Copy(IndyString, 9, 2)), StrToInt(Copy(IndyString, 11, 2)), StrToInt(Copy(IndyString, 13, 2)), 0); DateTimeToSystemTime(datetime,SystemTime); SystemTimeToFileTime(SystemTime,FFileTime); FileTimeToLocalFileTime(FFileTime,FFileTimeLocalized); FileTimeToSystemTime(FFileTimeLocalized,SystemTimeLocalized); //Localized DateTime Result:= DateTimeToStr(SystemTimeToDateTime( SystemTimeLocalized)); { ShowMessage( 'GMT Localized '+ DateTimeToStr( SystemTimeToDateTime( SystemTimeLocalized)) ); ShowMessage( 'GMT 0 (Not Localized) '+ DateTimeToStr(datetime) ); } end; |
Как собрать только директорию и её поддиректории?
По аналогии с файлами, только меняем условие…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
procedure TVisualFrame_PSFTPClient.ListDirAndAllSubDirs(dir:string); // will list all dirs to FDirs:TStringList var DL: TStringList; i: Integer; FileSizeString: string; FileSize:Int64; CurrentFileList: TStringList; M: TMatchCollection; j,k: integer; M2:TMatchCollection; RegEx:TRegEx; begin DL:=TStringList.Create; CurrentFileList:=TStringList.Create; try IdFTP.ChangeDir(Dir); IdFTP.List(DL, '', false); // <<<Listed all files and folders here... for i := 0 to IdFTP.DirectoryListing.Count-1 do CurrentFileList.Add(IdFTP.DirectoryListing[i].FileName); for i:=0 to DL.Count-1 do begin if (IdFTP.Size(dl.Strings[i])=-1) // If Folder then... and not (IdFTP.DirectoryListing[i].FileName.Contains('thumb')) then begin FDirs.Add(IdFTP.RetrieveCurrentDir+'/'+dl.Strings[i]); ListAllFilesCore2(dl.Strings[i]) //Recursion here... end; end; IdFTP.ChangeDirUp; IdFTP.List(DL, '', false); // << Critical!!! I Spent 5 hours to understand this... finally FreeAndNil(CurrentFileList); FreeAndNil(DL); end; end; |