Как узнать – полностью ли загрузился файл на FTP сервер? Идентичны ли файлы на клиенте и сервер? Можно написать свой алгоритм, проверяющий по тем или иным параметрам идентичность файлов, но в Indy уже всё готово и можно этим только пользоваться.
В Indy есть встроенный метод проверки верификации загрузки файла по FTP.
1 2 3 4 5 6 |
function VerifyFile( const ALocalFile: String; const ARemoteFile: String; const AStartPoint: Int64 = 0; const AByteCount: Int64 = 0 ): Boolean; overload; |
Вот что написано в документации
Internally, VerifyFile uses an instance of TIdHashMessageDigest5, TIdHashSHA1, or TIdHashCRC32 to calculate the checksum value for the contents of the local file using the ALocalFile argument.
AStartPoint indicates the initial position in the files to use when calculating the checksum values. When AStartPoint contains 0 (zero) or a positive Integer value, the stream in ALocalFile is positioned to to that location prior to starting the checksum calculation.
AByteCount indicates the number of bytes to include when performing the checksum calculation. The default value is 0, and indicates that the byte count should be derived from the size of the stream for the local file and the initial position indicated in AStartPoint.
VerifyFile calls an overloaded variant of the method to build and send an FTP command using an algorithm name and arguments as required for the operation. The checksum value from the remote FTP server is captured and compared to the value calculated for the local file. VerifyFile returns True when the local checksum and the remote checksum values are the same. VerifyFile returns False when the checksum values are not the same, or when the capability is not supported on the remote FTP server.
Use SupportsVerification to determine if the FTP server support the extensibility feature.
Как я применил это в своём примере?
1 2 3 4 5 6 7 8 9 10 11 12 |
//Проверяем файл IsFileVerified:= // << Свойство объекта fidFTP.VerifyFile( SourceFileName, FTPClient.FTPConnectionParams.UploadDir+'/'+DestFileName, 0, 0 ); |
Первый и второй аргументы это пути до файла на клиенте и сервере соответственно
Полностью, в процедуре Execute потока это выглядит вот так…
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 |
procedure TFTPUploadThread.Execute; var zero:Integer; i:integer; begin try // имитация ошибки в потоке { zero:=0; i:=5 div zero; } fidFTP:=TIdFTP.Create(nil); //Присваиваем события компоненту fidFTP fidFTP.OnAfterPut:=IdFTPAfterPut; fidFTP.OnWorkBegin:=IdFTPWorkBegin; fidFTP.OnWork:=IdFTPWork; fidFTP.OnStatus:=IdFTPStatus; fidFTP.OnWorkEnd:=IdFTPWorkEnd; fidFTP.Host:=FTPClient.FTPConnectionParams.Host;// 'localhost'; fidFTP.Port:=FTPClient.FTPConnectionParams.Port;// 22; fidFTP.Username:=FTPClient.FTPConnectionParams.Username; //'Login'; fidFTP.Password:=FTPClient.FTPConnectionParams.Password; //'Password'; fidFTP.Passive:=true; // <<Секрет успешной мультизагрузки... if not fidFTP.Connected then fidFTP.Connect; if not fidFTP.Connected then Exit; CriticalSection:=TCriticalSection.Create; CriticalSection.Enter; if FTPClient=nil then Exit; if SourceFileName='' then exit; try with FTPClient do begin //Enabled:=false; // <<<Блокировка формы //PutThreadsInProcess:=PutThreadsInProcess+1; begin fidFTP.MakeDir(FTPClient.FTPConnectionParams.UploadDir); fidFTP.ChangeDir(FTPClient.FTPConnectionParams.UploadDir); //Готовим место на сервере fidFTP.Allocate(FileSize); //fidFTP.TransferType := ftBinary; fidFTP.Put(SourceFileName,DestFileName); //Проверяем файл IsFileVerified:= fidFTP.VerifyFile( SourceFileName, FTPClient.FTPConnectionParams.UploadDir+'/'+DestFileName, 0, 0 ); Synchronize(MarkLabelIsVerified); end; //PutThreadsInProcess:=PutThreadsInProcess-1; //Enabled:=true; // Разблокировка формы //MultiUploadForm не использую, вместо этого на отдельной вкладке //if PutThreadsInProcess=0 then MultiUploadForm.Hide; // << Закроет окно по завершении end; finally //fidFTP.Disconnect; // Не включать... FreeAndNil(fidFTP); CriticalSection.Leave; FreeAndNil(FCriticalSection); end; except fEx := ExceptObject as Exception; Synchronize( QueryError ); end; { Place thread code here } 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 |
procedure TFTPUploadThread.MarkLabelIsVerified; var i: Integer; begin for i := 0 to FTPClient.UploadProgressList.Count-1 do begin if TfUploadProgress(FTPClient.UploadProgressList.Items[i]).SourceFileName= (SourceFileName) then with TfUploadProgress(FTPClient.UploadProgressList.Items[i]) do begin if IsFileVerified then lVerified.Caption:='Verified' else lVerified.Caption:='Not Verified'; end; end; end; |