PHP: Как я могу избежать чтения частичных файлов, которые были перенесены мне с FTP?

Файлы пересылаются на мой сервер через FTP. Я обрабатываю их с помощью PHP-кода в модуле Drupal. O / S – Ubuntu, а FTP-сервер – vsftp.

Через определенные промежутки времени я буду проверять новые файлы, обрабатывать их с помощью SimpleXML и перемещать их в папку «Готово». Как избежать обработки частично загруженного файла?

vsftp имеет lock_upload_files по умолчанию. Я думал о попытке сначала перенести файлы, ожидая, что переход произойдет в текущем загружаемом файле. Это, похоже, не происходит, по крайней мере, в командной строке. Если я начну загружать большой файл и перемещаться, он просто продолжает расти в новом месте. Я думаю, запись в каталоге не заблокирована.

Должен ли я попробовать fopen с режимом «a» или «r +», чтобы увидеть, удастся ли ему выполнить попытку загрузки в SimpleXML или есть лучший способ сделать это? Я предполагаю, что могу просто обнаружить потерю нагрузки SimpleXML, но … это кажется беспорядочным.

Я не контролирую отправителя. Они не будут загружать и переименовывать.

благодаря

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

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

Использование lock_upload_files конфигурации lock_upload_files vsftpd приводит к блокировке файлов с помощью функции fcntl() . Это помещает предупреждающую блокировку (ы) на загруженные файлы (файлы), которые находятся в процессе. Другим программам не нужно учитывать консультативные блокировки, а mv например, нет. Консультационные блокировки – это, как правило, только советы для программ, которые заботятся о таких замках. Вам нужен другой инструмент командной строки, такой как lockrun который уважает консультативные блокировки.

Примечание: lockrun должен быть скомпилирован WAIT_AND_LOCK(fd) чтобы использовать lockf() а не функцию flock() , чтобы работать с блокировками, заданными fcntl() в Linux. Поэтому, когда lockrun скомпилирован с использованием lockf() он будет взаимодействовать с блокировками, установленными vsftpd .

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

Команда lsof linux перечисляет открытые файлы в вашей системе. Я предлагаю выполнить его с помощью shell_exec() из PHP и shell_exec() вывод, чтобы узнать, какие файлы все еще используются вашим FTP-сервером.

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

Если размеры совпадают, загрузка выполняется, удаляет копию, работа с файлом.

Если размеры не совпадают, скопируйте файл еще раз.

повторение.

Вот еще одна идея: создать супер (но, надеюсь, не root) пользователя FTP, который может получить доступ к некоторым или ко всем каталогам загрузки. Вместо того, чтобы ваш PHP-код считывал загруженные файлы с диска, подключите его к локальному FTP-серверу и загрузите файлы. Таким образом vsftpd обрабатывает блокировку для вас (при условии, что вы lock_upload_files ). Вы сможете загружать файл только после того, как vsftp освободит блокировку эксклюзива / записи (как только запись будет завершена).

Вы упомянули попытку flock в своем комментарии (и как это не удается). Это действительно кажется болезненным, чтобы попытаться сопоставить любые блокировки vsftpd, но dio_fcntl может стоить выстрела.

Думаю, вы решили свою проблему много лет назад, но все же.

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