Передача большого файла через SFTP в PHP

У меня есть большой файл (200 МБ вверх). Мне нужно передать его через задание PHP cron. Использование Phpseclib дает следующую ошибку:

Разрешенный размер памяти 134217728 байт исчерпан (пытался выделить 4133 байта) в /app/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php

Есть ли способ сделать это с помощью PHP cron job?

Код прост: одна строка, где $localFile — это уже существующий CSV-файл.

$sftp->put('/Import/coupons/coupons_import_test.csv', $localFile, NET_SFTP_LOCAL_FILE);

ПС. Это необходимо сделать после того, как PHP сгенерирует этот файл в папке /tmp, поэтому необходимо учитывать время сценария передачи.

[Изменить] Я не собираюсь увеличивать лимит памяти, так как файлы позже могут быть большего размера. Решение, в котором я могу передавать файл по частям (режим добавления) или использовать какой-либо сценарий оболочки с PHP cron, может быть полезным.

Размер файла на удаленном сервере составляет 111,4 МБ, в то время как фактический файл намного больше на локальном.

[Редактировать после исправления] Проблема исчезла после перехода на версию 2.0.2 с версии 1.0. Мне пришлось изменить код для установки

$sftp->put('/Import/coupons/coupons_import.csv', $localFile, $sftp::SOURCE_LOCAL_FILE);

person Abhishek    schedule 05.07.2016    source источник
comment
comment
Что в вашем php.ini указано как memory_limit? Обычно что-то вроде 64M или 128M, вам нужно увеличить это.   -  person ggdx    schedule 05.07.2016
comment
Есть ли способ сделать это без увеличения лимита?   -  person Abhishek    schedule 05.07.2016
comment
Какая у вас версия Phpseclib?   -  person revo    schedule 14.07.2016
comment
вы можете сделать это с помощью сценария оболочки более простым способом, вам не нужен php и его ограничения. если вы думаете о том, чтобы сделать ш, я могу помочь с правильным ответом   -  person Santa's helper    schedule 14.07.2016
comment
Я спрашивал об этом раньше и не получил ответа, поэтому спрошу еще раз (поскольку вы только что опубликовали награду): можете ли вы опубликовать какой-нибудь код? Кроме того, какая часть файла загружена к тому времени, когда вы получаете ошибку памяти? Кроме того, идея Павла Дюбьеля тоже хороша, так что попробуйте, а если нет, то, возможно, ответьте на мой вопрос.   -  person neubert    schedule 14.07.2016
comment
Версия Phpseclib 1.0. Я отредактировал вопрос для кода (одна строка кода).   -  person Abhishek    schedule 15.07.2016
comment
Может быть, попробуйте открыть проблему здесь github.com/phpseclib/phpseclib и опубликовать журналы там.   -  person Pawel Dubiel    schedule 16.07.2016
comment
Можете ли вы также попробовать перенести этот файл на другой сервер, чтобы убедиться, что это та же проблема?   -  person Pawel Dubiel    schedule 16.07.2016
comment
Я думаю, вы должны увидеть это. Надеюсь, это поможет unix. stackexchange.com/questions/190537/   -  person Lokesh Pandey    schedule 18.07.2016


Ответы (3)


Phpseclib должен отлично справляться с передачей больших файлов без необходимости увеличения доступной памяти.

Я думаю, вы, вероятно, столкнулись со старой ошибкой «SSH2: не учитывать длину данных в зависимости от размера окна». Скорее всего, вы используете более старую версию Phpseclib (более старая неисправная версия поставляется даже с относительно новым программным обеспечением, таким как, например, Magento 1.9.*)

Проверьте свою версию, если она не самая последняя, ​​повторно загрузите ее с https://github.com/phpseclib/phpseclib.

person Pawel Dubiel    schedule 14.07.2016
comment
Я использую phpseclib 1.0 от композитора, требующего настройки героку. - person Abhishek; 15.07.2016
comment
Я не знаю, была ли эта ошибка в версии 1.0, на которую вы указали, вызывала проблему, но когда я перешел на версию 2.0.2, проблема исчезла. Хотя мне нужно немного изменить код. - person Abhishek; 18.07.2016
comment
@aeonsleo - Какую версию 1.0 вы использовали? Похоже, что composer update мог бы также исправить проблему, если бы 2.0.2 это сделало.. - person neubert; 18.07.2016

Вместо того, чтобы видеть код, который вы используете, я предполагаю, что вы пытаетесь загрузить файл размером 200 МБ в виде строки и пытаетесь загрузить его в виде строки. например. $sftp->put('filename.remote', file_get_contents('filename.local'));. Если это так, попробуйте это вместо этого:

$sftp->put('filename.remote', 'filename.local', NET_SFTP_LOCAL_FILE);
person neubert    schedule 06.07.2016
comment
Я делаю именно так, как вы упомянули. - person Abhishek; 06.07.2016
comment
Чтобы прокомментировать дальше, мне нужно увидеть код. Вы можете отредактировать его в своем оригинальном посте. Кроме того, какая часть файла загружена к тому времени, когда вы получаете ошибку памяти? - person neubert; 07.07.2016

На самом деле это немного изменилось с версией phpseclib >= 2.0.5. Вы должны включить пространство имен use phpseclib\Net\SFTP; , а затем сделать что-то вроде этого:

$sftp->put('filename.remote', 'filename.local', SFTP::SOURCE_LOCAL_FILE);
person Bitclaw    schedule 01.06.2017