PHP загружает несколько файлов, используя FWRITE и SSH2 - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь загрузить несколько файлов на сайт SFTP из локального каталога.

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

$localFile_xml = "C:\xml\Race_" . $value; 
chdir($localFile_xml); 


//This successfully lists the files
foreach (glob("*.xml") as $filename) {
    echo "$filename size " . filesize($filename) . "\n";
}

$remote_XMLfiles = "/FTP/XML/Race_" . $value;

$xmlstream = fopen("ssh2.sftp://$sftp" . $remote_XMLfiles, 'w');

foreach (glob("*.xml") as $filename) {
    $xmlfile = file_get_contents($localFile_xml);
    fwrite($xmlstream, $xmlfile);
    fclose($xmlstream);

}

Я верю, что это так, но последний бит не могу исправить.

Заранее большое спасибо

1 Ответ

0 голосов
/ 05 февраля 2019

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

Как упоминалось в моих комментариях, ваш кодпохоже, пытается использовать file_get_contents в локальном каталоге, что недопустимо.Также кажется, что вы пытались сделать то же самое на $xmlstream, что должно выполняться для каждого файла, а не для каталога.Предполагая, что 'C:\\xml\\Race_' . $value; является каталогом, подобным C:\\xml\\Race_1, а не файлом.

Некоторые незначительные проблемы для проверки ресурсов и специфические проблемы Windows, которые необходимо устранить:

  • Разделители каталогов Windows должны быть записаны как \\ (даже при использовании одинарных кавычек), поскольку \ является escape-последовательностью, поэтому \x \t \n \r \' \" \\ рассматривается как специальные символы.

  • При использовании fopen($path, $mode) рекомендуется указывать флаг b в качестве последнего символа режима, чтобы обеспечить безопасность двоичного файла (дословно) и избежать неоднозначности между операционными системами.В качестве альтернативы в Windows укажите режим t для прозрачного перевода \n в \r\n (желательно только для текстовых файлов) .

    • $mode = 'rb' (чтение в двоичном формате)
    • $mode = 'rt' (чтение в текстовом режиме)
  • При работе в сетиДля потоков рекомендуется проверить, что поток успешно записал весь свой контент.Ниже приведена функция fwrite_stream из руководства по PHP.

Пример

try {
    //--- example purposes only ---
    //use your own ssh2_connnect, ssh2_auth_password, ssh2_sftp
    if (!$ssh2 = ssh2_connect('192.168.56.101', 22)) {
        throw new \RuntimeException('Unable to connect to remote host');
    }
    if (!ssh2_auth_password($ssh2, 'root', '')) {
        throw new \RuntimeException('Unable to Authenticate');
    }
    if (!$sftp = ssh2_sftp($ssh2)) {
        throw new \RuntimeException('Unable to initialize SFTP');
    }

    $value = '1'; 
   //--- end example purposes only ---

    $localFile_xml = 'C:\\xml\\Race_' . $value;
    if (!$localFile_xml || !is_dir($localFile_xml)) {
        throw new \RuntimeException('Unable to retrieve local directory');
    }

    //retrieve list of XML files
    $iterator = new \GlobIterator($localFile_xml . '/*.xml',
        \FilesystemIterator::KEY_AS_PATHNAME |
        \FilesystemIterator::CURRENT_AS_FILEINFO |
        \FilesystemIterator::SKIP_DOTS
    );
    if (!$iterator->count()) {
        throw new \RuntimeException('Unable to retrieve local files');
    }

    $success = [];
    $remote_XMLfiles = '/FTP/XML/Race_' . $value;
    $remote_XMLpath = "ssh2.sftp://$sftp" . $remote_XMLfiles;

    //ensure the remote directory exists
    if (!@mkdir($remote_XMLpath, 0777, true) && !is_dir($remote_XMLpath)) {
        throw new \RuntimeException(sprintf('Unable to create remote directory "%s"', $remote_XMLpath));
    }

    /**
     * @var string $filepath
     * @var \SplFileInfo $fileinfo
     */
    foreach ($iterator as $filepath => $fileinfo) {
        $filesize = $fileinfo->getSize();
        printf("%s size %d\n", $filepath, $filesize);
        try {
            //open local file resource for binary-safe reading
            $xmlObj = $fileinfo->openFile('rb');
            //retrieve entire file contents
            if (!$xmlData = $xmlObj->fread($filesize)) {
                //do not permit empty files
                printf("No data found for \"%s\"\n", $filepath);
                continue;
            }
        } finally {
            //shortcut to close the opened local file resource on success or fail
            $xmlObj = null;
            unset($xmlObj);
        }

        try {
            $remote_filepath = $remote_XMLpath . '/' . $fileinfo->getBasename();
            //open a remote file resource for binary-safe writing
            //using current filename, overwriting the file if it already exists
            if (!$xmlstream = fopen($remote_filepath, 'wb')) {
                throw new \RuntimeException(sprintf('Unable to create remote file "%s"', $remote_filepath));
            }
            //write the local file data to the remote file stream
            if (false !== ($bytes = fwrite_stream($xmlstream, $xmlData))) {
                $success[] = [
                    'filepath' => $filepath,
                    'remote_filepath' => $remote_filepath,
                    'bytes' => $bytes,
                ];
            }
        } finally {
            //shortcut to ensure the xmlstream is closed on success or failure
            if (isset($xmlstream) && is_resource($xmlstream)) {
                fclose($xmlstream);
            }
        }
    }

    //testing purposes only to show the resulting uploads
    if (!empty($success)) {
        var_export($success);
    }
} finally {
    //shortcut to disconnect the ssh2 session on success or failure
    $sftp = null;
    unset($sftp);
    if (isset($ssh2) && is_resource($ssh2)) {
        ssh2_disconnect($ssh2);
    }
}
/*
 * Taken from PHP Manual
 * Writing to a network stream may end before the whole string is written.
 * Return value of fwrite() may be checked
 */
function fwrite_stream($fp, $string)
{
    for ($written = 0, $writtenMax = strlen($string); $written < $writtenMax; $written += $fwrite) {
        $fwrite = fwrite($fp, substr($string, $written));
        if (false === $fwrite) {
            return $written;
        }
    }

    return $written;
}

NOTE

Все файловые операции будут созданы с использованием пользователя ssh2_auth_password в качестве владельца / группы.Вы должны убедиться, что указанный пользователь имеет доступ на чтение и запись к нужным каталогам.

Используйте соответствующие маски файлов, чтобы обеспечить требуемые права доступа к файлам / каталогам

  • 0777 (по умолчанию) позволяеткаждый может читать, писать, выполнять!
  • 0750 обычно требуется для каталогов
  • 0640 обычно требуется для отдельных файлов
  • использовать chmod($path, 0750) для изменения прав доступа к удаленному файлу (файлам)
  • используйте chown($path, 'user') для изменения владельца удаленного файла (файлов)
  • используйте chgrp($path, 'group') для изменения группы в удаленном файле (файлах)

Результат

C:\xml\Race_1\file1.xml size 9
C:\xml\Race_1\file2.xml size 11
array (
  0 =>
  array (
    'filepath' => 'C:\\xml\\Race_1\\file1.xml',
    'remote_filepath' => 'ssh2.sftp://Resource id #5/FTP/XML/Race_1/file1.xml',
    'bytes' => 9,
  ),
  1 =>
  array (
    'filepath' => 'C:\\xml\\Race_1\\file2.xml',
    'remote_filepath' => 'ssh2.sftp://Resource id #5/FTP/XML/Race_1/file2.xml',
    'bytes' => 11,
  ),
)
...