PHP: Как мне избежать чтения частичных файлов, которые передаются мне по FTP? - PullRequest
13 голосов
/ 29 апреля 2011

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

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

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

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

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

Спасибо

Ответы [ 6 ]

4 голосов
/ 09 августа 2012

Использование параметра конфигурации 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, чтобы пропустить текущие загрузки.

3 голосов
/ 29 апреля 2011

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

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

2 голосов
/ 29 апреля 2011

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

1 голос
/ 29 апреля 2011

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

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

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

повторить.

0 голосов
/ 06 августа 2014

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

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

0 голосов
/ 10 января 2014

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

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

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