PHP: Как я могу избежать чтения частичных файлов, которые были перенесены мне с FTP?
Файлы перенаправляются на мой сервер через FTP. Я обрабатываю их с помощью PHP-кода в модуле Drupal. O/S - Ubuntu, а FTP-сервер - vsftp.
Через регулярные промежутки времени я буду проверять наличие новых файлов, обрабатывать их с помощью SimpleXML и перемещать их в папку "Готово". Как избежать обработки частично загруженного файла?
vsftp имеет значение lock_upload_files по умолчанию yes. Я думал о попытке сначала перенести файлы, ожидая, что переход произойдет в текущем загружаемом файле. Это, похоже, не происходит, по крайней мере, в командной строке. Если я начну загружать большой файл и перемещаться, он просто продолжает расти в новом месте. Я думаю, что запись в каталоге не заблокирована.
Должен ли я попытаться fopen с режимами 'a' или 'r +' только для того, чтобы убедиться, что это удается, прежде чем пытаться загрузить в SimpleXML или есть лучший способ сделать это? Думаю, я мог просто обнаружить потерю нагрузки SimpleXML, но... это кажется грязным.
У меня нет контроля над отправителем. Они не будут загружать и переименовывать.
Спасибо
Ответы
Ответ 1
Если блокировка не работает, я не знаю, какое решение было бы чистым/простым, как вам хотелось бы. Вы могли бы получить обоснованное предположение, не обрабатывая файлы, чье последнее измененное время (которое вы можете получить с помощью filemtime()
) находится за последние x минут.
Если вам нужна более высокая степень достоверности, вы можете проверить и сохранить каждый размер файла (используя filesize()
) в простой базы данных и каждые x минут проверяют новый размер на старый размер. Если размер не изменился за x минут, вы можете предположить, что больше ничего не отправляется.
Ответ 2
Использование опции lock_upload_files
конфигурации vsftpd
приводит к блокировке файлов с помощью функции fcntl()
. Это помещает предупреждающую блокировку на загруженные файлы (файлы), которые находятся в процессе. Другим программам не нужно рассматривать консультативные блокировки, а mv
, например, нет. Консультационные блокировки - это, как правило, только советы для программ, которые заботятся о таких замках.
Вам понадобится другой инструмент командной строки, такой как lockrun
, который соблюдает консультативные блокировки.
Примечание. lockrun
должен быть скомпилирован макросом WAIT_AND_LOCK(fd)
для использования функции lockf()
, а не flock()
, чтобы работать с блокировками, установленными fcntl()
под Linux. Поэтому, когда lockrun
скомпилируется с использованием lockf()
, то он будет взаимодействовать с блокировками, установленными vsftpd
.
С такими функциями (lockrun
, mv
, lock_upload_files
) вы можете создать оболочку script или аналогичную, которая перемещает файлы один за другим, проверяя, был ли файл заблокирован заранее, и удерживая на нем консультативную блокировку пока файл перемещен. Если файл заблокирован с помощью vsftpd
, то lockrun
может пропустить вызов на mv
, чтобы пропускать загружаемые загрузки.
Ответ 3
Команда lsof
linux перечисляет открытые файлы в вашей системе. Я предлагаю выполнить его с помощью shell_exec()
из PHP и проанализировать вывод, чтобы узнать, какие файлы все еще используются вашим FTP-сервером.
Ответ 4
Подбирая предыдущий ответ, вы можете скопировать файл, а затем сравнить размеры скопированного файла и исходного файла с фиксированным интервалом.
Если размеры совпадают, загрузка выполняется, удалите копию, работайте с файлом.
Если размеры не совпадают, скопируйте файл еще раз.
повторить.
Ответ 5
Вот еще одна идея: создать супер (но, надеюсь, не root) пользователя FTP, который может получить доступ к некоторым или ко всем каталогам загрузки. Вместо того, чтобы ваш PHP-код считывал загруженные файлы с диска, подключите его к локальному FTP-серверу и загрузите файлы. Таким образом vsftpd обрабатывает блокировку для вас (при условии, что вы оставите lock_upload_files
включенным). Вы сможете загружать файл только после того, как vsftp освободит блокировку исключительной записи/записи (как только запись завершена).
Вы упомянули попытку flock
в своем комментарии (и как это не удается). Это действительно кажется болезненным, чтобы попытаться сопоставить любые блокировки vsftpd, но dio_fcntl
может стоить того.
Ответ 6
Я думаю, вы решили свою проблему много лет назад, но все же.
Если вы используете какой-либо шаблон для поиска необходимых файлов, вы можете попросить, чтобы сторона, загружающая файл, использовала другое имя и переименовывала файл после завершения загрузки.
Ответ 7
Вы должны проверить скрытые магазины в proftp, более подробную информацию здесь:http://www.proftpd.org/docs/directives/linked/config_ref_HiddenStores.html