Обход ошибки PHP 7 SSH2.SFTP stat()

У меня есть приложение, которое использует SFTP-соединение для загрузки файлов. Он работал правильно в PHP 5.6, не так много в PHP 7. Ошибка, которую я получаю, выглядит следующим образом:

Предупреждение PHP: размер файла (): ошибка статистики для ssh2.sftp ...

Мой код выглядит следующим образом:

 public function retrieveFiles($downloadTargetFolder,$remoteFolder = '.') {

            $fileCount = 0;

                echo "\nSftpFetcher retrieveFiles\n";

        $con = ssh2_connect($this->host,$this->port) or die("Couldn't connect\n");
        if($this->pubKeyFile){
                $isAuth = ssh2_auth_pubkey_file($con, $this->user, $this->pubKeyFile, $this->privKeyFile);
        } else {
                $isAuth = ssh2_auth_password($con,  $this->user,  $this->pass);
        };


        if ($isAuth) {

                $sftp = ssh2_sftp($con);
                $rd = "ssh2.sftp://{$sftp}{$remoteFolder}";

                if (!$dir = opendir($rd)) {
                        echo "\nCould not open the remote directory\n";
                } else {
                        $files = array();
                                while (false != ($file = readdir($dir))) {
                                    if ($file == "." || $file == "..")
                                        continue;
                                    $files[] = $file;
                                }

                        if (is_array($files)) {
                            foreach ($files as $remoteFile) {
                                                echo "\ncheck file: $remoteFile vs filter: " . $this->filter."\n";
                                if ($this->filter !== null && strpos($remoteFile,$this->filter) === false) {
                                    continue;
                                }
                                                echo "file matched\n";
                                $localFile = $downloadTargetFolder . DIRECTORY_SEPARATOR . basename($remoteFile);


                                //$result = ftp_get($con,$localFile,$remoteFile,FTP_BINARY);
                                $result = true;
                                // Remote stream
                                if (!$remoteStream = @fopen($rd."/".$remoteFile, 'r')) {
                                        echo "Unable to open the remote file $remoteFolder/$remoteFile\n";
                                        $return = false;
                                } else {
                                        // Local stream
                                        if (!$localStream = @fopen($localFile, 'w')) {
                                                echo "Unable to open the local file $localFile\n";
                                                $return = false;
                                        } else {
                                                // Write from our remote stream to our local stream

                                                $read = 0;
                                                $fileSize = filesize($rd."/".$remoteFile);
                                                while ($read < $fileSize && ($buffer = fread($remoteStream, $fileSize - $read))) {
                                                        $read += strlen($buffer);
                                                        if (fwrite($localStream, $buffer) === FALSE) {
                                                                echo "Unable to write the local file $localFile\n";
                                                                $return = false;
                                                                break;
                                                        }
                                                }


                                                echo "File retrieved";
                                                // Close
                                                fclose($localStream);
                                                fclose($remoteStream);

                                        }

                                }

                                if ($result) {
                                    $fileCount++;
                                }
                            }
                        }

                        ssh2_exec($con, 'exit');
                        unset($con);
                }

        } else {
                echo "Error authenticating the user ".$this->user."\n";
        }

            return $fileCount;

    }
}

После некоторых исследований я обнаружил проблему со stat():

http://dougal.gunters.org/blog/2016/01/18/wordpress-php7-and-updates-via-php-ssh2/ https://bugs.php.net/bug.php?id=71376

Мой вопрос

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

Моя версия PHP: PHP 7.0.8-0ubuntu0.16.04.3 (cli) (NTS)


person mwex501    schedule 01.12.2016    source источник


Ответы (1)


Цитируя исправление PHP ssh2.sftp opendir/readdir,

Вместо использования "ssh2.sftp://$sftp" в качестве пути потока преобразуйте $sftp в целое число, например: "ssh2.sftp://" . intval($sftp) . "/". Тогда он будет работать нормально.

Причина изменения следующая:

PHP 5.6.28 (и, по-видимому, 7.0.13) представил исправление безопасности для синтаксического анализа URL-адресов, из-за которого интерполяция строки дескриптора ресурса $sftp больше не распознавалась как действительный URL-адрес. В свою очередь, это приводит к сбою opendir(), readdir() и т. д., когда вы используете ресурс $sftp в строке пути после обновления до одной из этих версий PHP.

Что касается других библиотек... я знаю только другую библиотеку phpseclib, которая имеет своего рода эмулятор для libssh2:

https://github.com/phpseclib/libssh2-compatibility-layer

Этот «эмулятор», безусловно, можно было бы улучшить. Например, нужно добавить файл composer.json и т. д.

person neubert    schedule 03.12.2016
comment
Просто столкнулся с этим, и ваш ответ спас положение. Спасибо! - person Revent; 08.02.2017
comment
Спасибо :) странно возникла эта проблема после обновления ОС, Php 5.6, intval сделал свое дело. Теперь я потратил на проблему всего один час, в отличие от многих других. - person David Kaplan; 21.02.2017