Как определить, завершился ли перенос файла, чтобы можно было копировать - PullRequest
0 голосов
/ 26 мая 2010

Каков наилучший способ убедиться, что файл, передаваемый по ftp, завершен до того, как другой процесс попытается переместить / скопировать этот файл?

Ответы [ 5 ]

3 голосов
/ 26 мая 2010

Как насчет ftp-сервера? Возможно, подключаемый модуль для сервера, который будет запускать событие всякий раз, когда будет получен положительный ответ о завершении (2xx Server Return), когда передача файла завершена.

Отправка файлов через ftp может быть прервана и приостановлена ​​на неопределенное время, и вы никогда не сможете предположить, что они закончены. Я думаю, что единственный способ быть уверенным в завершении (или даже в передаче файла без ошибок) - через FTP-сервер.

1 голос
/ 26 мая 2010

1) Если вы контролируете отправку; после того, как вы отправите фактический файл, ftp пустой контрольный файл с тем же именем, но с другим .ext. Проверьте этот контрольный файл, и фактический файл будет в порядке.

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

Пример кода для объяснения 2)

const
  LastWriteAccessDwell = 30; // seconds
var
  SR: TSearchRec;
  LastAccess: TDateTime;

...
if LastWriteWithin( SR.FindData.ftLastWriteTime, LastWriteAccessDwell, LastAccess ) then
begin
  WriteText( format('Last Access @%s was less than %d seconds.', [DateTimeToStr(LastAccess), LastWriteAccessDwell]) );
  continue;
end;

function LastWriteWithin( FileTime: TFileTime; const Seconds: Cardinal; out LastAccess: TDateTime ): boolean;
var
  LocalFileTime: TFileTime;
  iFileAge: integer;
begin
  if Not( FileTimeToLocalFileTime( FileTime, LocalFileTime )
      and FileTimeToDosDateTime(LocalFileTime, LongRec(iFileAge).Hi, LongRec(iFileAge).Lo) ) then
    RaiseLastOSError;

  LastAccess:= FileDateToDateTime(iFileAge);
  result:= WithinPastSeconds( Now, LastAccess, Seconds );
end;
0 голосов
/ 23 марта 2011

Ответ robsoft может быть улучшен путем генерации контрольной суммы (MD5, sha1 и т. Д.) На стороне отправителя. Как только получатель увидит имя файла. 16384 = размер файла 16384, он также может сравнить контрольные суммы, чтобы быть на 100% уверенным, что файл получен нормально!

@ Linux: см. Sha1sums, md5sums

0 голосов
/ 26 мая 2010

Я всегда делал следующее:

a) get the size of the file, in bytes
b) append this to the filename eg MyFile.Dat.16384
c) send the file over ftp etc

на другом конце у вас есть программа, которая просматривает входящую папку FTP. Каждую секунду или около того (подстраиваясь под костюм) вы сканируете папку на наличие файлов, и когда вы обнаруживаете файл, размер файла которого соответствует строке в конце имени файла, вы можете быть достаточно уверены, что он прибыл и его можно свободно перемещать, переименовывать что угодно.

Мы встроили некоторую логику в сканирование, чтобы файл не был атакован до тех пор, пока он не обнаружился во второй раз при сканировании, просто для того, чтобы в последнюю секунду или около того возможная обработка / разблокировка со стороны FTP сервер.

Это довольно просто для Delphi, это просто структура типа findfirst / findnext / findclose в цикле, работающем по таймеру. Выключите таймер при запуске сканирования и перезапустите его, когда закончите.

0 голосов
/ 26 мая 2010

Не знаю, как работает ваш FTP-сервер, но я бы периодически проверял, можно ли открыть файл исключительно, так как он, вероятно, открыт для записи во время процесса передачи файла и закрыт после завершения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...