Перейти к содержимому

Файловый обмен по FTP и SFTP - доступ, расписание, разбор

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

Что нужно знать заранее

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

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

Появление файла в папке ещё не означает, что он дописан до конца. Забор в момент записи даёт обрезанную выгрузку, и разбор такого файла портит данные вместо их обновления.

Шаги

  1. Договориться с партнёром о протоколе, папке, имени файлов и расписании их появления.
  2. Настроить доступ по ключу и проверить подключение отдельным скриптом с консоли.
  3. Забирать файлы заданием по расписанию, обязательно проверяя готовность каждого файла.
  4. Разбирать выгрузку порциями и вести подробный журнал каждого запуска обмена.
  5. Складывать разобранные файлы в архив и чистить этот архив по расписанию.

Решение

Проверяем подключение отдельным скриптом:

Окно терминала
sftp -i /home/bitrix/.ssh/partner_key partner@files.example.com <<'EOF'
ls -l /outbox
bye
EOF
# проверка руками до написания кода экономит час на разборе прав доступа

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

Забираем файлы из кода:

$conn = ssh2_connect('files.example.com', 22);
ssh2_auth_pubkey_file($conn, 'partner', '/home/bitrix/.ssh/partner_key.pub',
'/home/bitrix/.ssh/partner_key');
$sftp = ssh2_sftp($conn);
$files = scandir('ssh2.sftp://' . (int)$sftp . '/outbox');
// расширение ssh2 доступно не везде: на хостинге проверяют его наличие заранее

Проверяем готовность файла:

$path = 'ssh2.sftp://' . (int)$sftp . '/outbox/' . $name;
clearstatcache();
$size1 = filesize($path); sleep(3); clearstatcache();
if ($size1 !== filesize($path)) { continue; } // файл ещё пишется, берём в следующий раз

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

Разбираем выгрузку порциями:

$fh = fopen($localPath, 'r');
fseek($fh, (int)\Bitrix\Main\Config\Option::get('vendor.module', 'import_offset', 0));
for ($i = 0; $i < 500 && ($row = fgetcsv($fh, 0, ';')); $i++) { processRow($row); }
\Bitrix\Main\Config\Option::set('vendor.module', 'import_offset', ftell($fh));
// смещение в файле переживает перезапуск и разрывы по времени выполнения

Складываем разобранное в архив:

Окно терминала
mv /home/bitrix/exchange/in/price-2026-08-20.csv /home/bitrix/exchange/done/
find /home/bitrix/exchange/done/ -type f -mtime +30 -delete
# архив за месяц спасает при разборе жалоб «а что вы нам прислали»

Типичные проблемы

Разобранная выгрузка оказалась обрезанной.

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

Задание падает на подключении к папке партнёра.

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

Обмен работает вручную и не работает по расписанию.

Задание выполняется под другим пользователем, у которого нет ключа и прав. Скрипт запускают под тем же пользователем, что и задание в расписании.

Разбор большого файла не доходит до конца.

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

Папка обмена разрослась до тысяч файлов.

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

Частые вопросы

Чем защищённый протокол лучше обычного?

Он не передаёт пароль и данные открытым текстом и работает через один порт. Обычный протокол оставляют только там, где партнёр не может иначе.

Как понять, что файл дописан?

Сравнить размер дважды с паузой или договориться о файле-метке рядом с выгрузкой. Второй способ надёжнее, но требует согласия партнёра.

Забирать файлы агентом или заданием сервера?

Заданием сервера: оно не зависит от посещаемости сайта и не мешает посетителям. Агент годится для небольших файлов и редких обменов.

Что делать при пропущенном файле?

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

Как отлаживать такой обмен?

Журналом каждого запуска: имя файла, размер, число строк и время разбора. Без журнала разбор жалоб превращается в гадание.

Смежное

Первоисточник