Как определить, передается ли файл по FTP - PullRequest
25 голосов
/ 30 августа 2011

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

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

Ответы [ 5 ]

9 голосов
/ 30 августа 2011

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

[Это также позволяет вам удалить неудачные (частичные) передачи по истечении заданного периода времени, если вам это нужно.]

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

Другая схема (которая также требует сотрудничества с загрузчиком) может включать загрузку сначала хеша и размера файла, а затем самого файла. Это позволяет вам знать как когда передача сделана, так и согласована ли она. (Существует множество вариантов этой идеи.)

Что-то, что не требует взаимодействия с клиентом, проверяет, открыт ли файл другим процессом или нет. (То, как вы это делаете, зависит от ОС - я не знаю встроенного PHP, который делает это. lsof и / или fuser можно использовать на различных платформах типа Unix, для этого в Windows есть API.) Если файл открыт у другого процесса, скорее всего, он еще не завершен.

Обратите внимание, что этот последний подход может быть небезопасным, если вы разрешаете перезапуск / возобновление загрузки или если программное обеспечение вашего FTP-сервера не сохраняет файл открытым в течение всего времени передачи, поэтому YMMV.

5 голосов
/ 30 августа 2011

Администратор нашего сервера предложил ftpwho, который выводит, какие файлы в данный момент передаются.

http://www.castaglia.org/proftpd/doc/ftpwho.html

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

4 голосов
/ 30 августа 2011

Некоторые FTP-серверы позволяют запускать команды, когда происходит определенное событие.Так что, если ваш FTP-сервер позволяет это, вы можете создать простую схему сигнализации, чтобы ваше приложение знало, что файл был загружен более или менее успешно (более или менее потому, что вы не знаете, намеревался ли пользователь загрузить файлполностью или по частям).Схема сигнализации может быть такой же простой, как создание файла «uploaded_file_name.ext.complete», и вы будете отслеживать наличие файлов с расширением «.complete».

Теперь вы можете проверить, можете ли вы открыть файл дляпишу.Большинство FTP-серверов не позволяют вам сделать это, если файл загружается.

Еще один подход, упомянутый Мэтом, заключается в использовании системных методов для проверки, открывается ли файл другим процессом.

3 голосов
/ 20 июня 2013

Лучший способ проверить это попытаться получить эксклюзивную блокировку файла с помощью flock. Процесс sftp / ftp будет использовать библиотеки fopen.

// try and get exclusive lock on file
$fp = fopen($pathname, "r+");

if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
    flock($fp, LOCK_UN);    // release the lock
fclose($fp);
}
else {
    error_log("Failed to get exclusive lock on $pathname. File may be still uploading.");
}
1 голос
/ 04 апреля 2017

Это не очень хороший трюк, но он прост :-), то же самое вы можете сделать с filemtime

$result = false;
$tryies = 5;
if (file_exists($filepath)) {
    for ($i=0; $i < $tryies; $i++) { 
        sleep(1);
        $filesize[] = filesize($filepath);
    }
    $filesize = array_unique($filesize);
    if (count($filesize) == 1) {
        $result = true;
    } else {
        $result = false;
    }
}

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