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

Я пытаюсь загрузить несколько файлов на сайт 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);

}

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

Огромное спасибо заранее

Похоже, вы звоните fclose, но снова не fopen. Вам нужно будет повторно открыть закрытый ресурс.

Will B. 02.02.2019 05:32

Спасибо за помощь, к сожалению, это не помогло.

MdM 02.02.2019 06:09

Запутался в том, чего именно вы пытаетесь достичь. Похоже, ваш код повторно записывает одни и те же данные $xmlfile в $xmlstream. но вообще не использует $filename в итерации foreach к $xmlstream и не изменяет файлы $xmlstream. file_get_contents($localFile_xml) должен возвращать false, так как это похоже на каталог. Удаленный файл уже существует или его следует создать, если нет? Пожалуйста, обновите вопрос, указав свой функциональный код одного файла.

Will B. 05.02.2019 03:19

Привет, вы, вероятно, правы, что мой код повсюду, я новичок в кодировании и выше моих сил в том, чего я пытаюсь достичь. Итак, я пытаюсь загрузить все XML-файлы из папки на локальном сервере в уже созданную папку на безопасном FTP-сервере. Мне удалось сделать один файл одновременно, но этот подход неэффективен. Спасибо

MdM 05.02.2019 04:23

Что вы подразумеваете под "не помогло", каков был эффект? Потому что Фырье прямо здесь. Прежде чем двигаться дальше, вы должны включить отчет об ошибках, потому что он просто предполагает обратное. Угадывание для детей.

Daniel W. 05.02.2019 16:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
5
1 013
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

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

  • Разделители каталогов Windows должны быть записаны как \\ (даже если используя одинарные кавычки), так как \ является управляющей последовательностью это заставляет \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

All file operations will be created using the ssh2_auth_password user as the owner/group. You must ensure the specified user has read and write access to the desired directories.

Use the appropriate file masks to ensure desired file/directory permissions

  • 0777 (default) allows everyone to read, write, execute!
  • 0750 is typically desired for directories
  • 0640 is typically desired for individual files
  • use chmod($path, 0750) to change permissions on the remote file(s)
  • use chown($path, 'user') to change the owner on the remote file(s)
  • use chgrp($path, 'group') to change the group on the remote file(s)

Результат

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,
  ),
)

Привет, Fyrye ... Прежде всего, спасибо, вы помогли мне не только с моей проблемой, но и нашли время, чтобы объяснить, где я ошибся. Я очень ценю ваше время, усилия и рекомендации. еще раз спасибо.

MdM 16.02.2019 01:23

Другие вопросы по теме