By default, \phpseclib\Net\SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SFTP::get(), you will get a file, twelve bytes
long, containing 'filename.ext' as its contents.
Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
large $remote_file will be, as well.
Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number of bytes to return, and returns a string if there is some data or null if there is no more data
If $data is a resource then it'll be used as a resource instead.
Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
care of that, yourself.
$mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with
$mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following:
self::SOURCE_LOCAL_FILE | self::RESUME
If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace
self::RESUME with self::RESUME_START.
If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed.
$start and $local_start give you more fine grained control over this process and take precident over self::RESUME
when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle
of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the
middle of one.
Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE.
public put ( string $remote_file, string | resource $data, integer $mode = self::SOURCE_STRING, integer $start, integer $local_start, callable | null $progressCallback = null ) : boolean | ||
$remote_file | string | |
$data | string | resource | |
$mode | integer | |
$start | integer | |
$local_start | integer | |
$progressCallback | callable | null | |
return | boolean |
/** * @return bool * * @throws \Exception */ public function send() { $sent = true; $files = $this->backup->getFilesTobackup(); if (!empty($files)) { foreach ($files as $file => $name) { $upload = $this->connection->put($this->folder . '/' . $name, $file, LibSFTP::SOURCE_LOCAL_FILE); if (!$upload) { $sent = false; echo 'SFTP upload manqu�e de ' . $file . ' vers ' . $this->folder . $name; } } } $streams = $this->backup->getStreamsTobackup(); if (!empty($streams)) { foreach ($streams as $name => $stream) { $upload = $this->connection->put($this->folder . '/' . $name, $stream); if (!$upload) { echo 'SFTP upload manqu�e de ' . $name . ' vers ' . $this->folder . $name; $sent = false; } } } if (!$sent) { throw new \Exception('At least an upload didnt work.'); } return $sent; }
/** * {@inheritdoc} */ public function putFile($sourceFilename, $destinationFilename) { if ($this->isConnected()) { return $this->connection->put($destinationFilename, $sourceFilename, SFTP::SOURCE_LOCAL_FILE); } return false; }
public function uploadFile($File) { $this->persistConnection(); if (!$this->Connection->put(basename($File), file_get_contents($File))) { throw new ComponentException(__METHOD__ . ': Failed'); } return $this; }
/** * Upload file to remote account. * * @param string $absolutePathRemoteFile The absolute path to remote file (new) * @param string $absolutePathLocalFile The absolute path to local file * * @return SftpInterface The current instance * * @api */ public function uploadFile(string $absolutePathRemoteFile, string $absolutePathLocalFile) : SftpInterface { /** * Common stream source types: * - static::SOURCE_STRING * - static::SOURCE_CALLBACK * - static::SOURCE_LOCAL_FILE */ file_exists($absolutePathLocalFile) && is_readable($absolutePathLocalFile) ? $this->netSftp->put($absolutePathRemoteFile, $absolutePathLocalFile, static::SOURCE_LOCAL_FILE) : $this->logError('AbstractSftp::uploadFile()', 'cannot read/find local file (check local path): ' . $absolutePathLocalFile, 'E085'); $this->checkForSameFileSize($absolutePathRemoteFile, $absolutePathLocalFile); return $this; }
/** * {@inheritdoc} */ public function upload($local, $remote) { $this->checkConnection(); $dir = dirname($remote); if (!isset($this->directories[$dir])) { $this->sftp->mkdir($dir, -1, true); $this->directories[$dir] = true; } if (!$this->sftp->put($remote, $local, SFTP::SOURCE_LOCAL_FILE)) { throw new \RuntimeException(implode($this->sftp->getSFTPErrors(), "\n")); } }
public function putContent($content, $dest) { if (false === $this->isConnected()) { $this->connectAndLogin(); } $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_PUT_CONTENT, new TransporterEvent($this, array('dest' => $dest, 'content' => $content))); $success = $this->sftp->put($dest, $content, PhpseclibSFTP::SOURCE_STRING); if (!$success) { // maybe the parent directory doesnt exist; try to create it and try again $pwd = dirname($dest); if (false === $this->exists($pwd)) { $this->mkdir($pwd); // retry try to put $success = $this->sftp->put($dest, $content, PhpseclibSFTP::SOURCE_STRING); if (!$success) { throw new \RuntimeException('Something went wrong: ' . "\n" . implode("\n", $this->sftp->getSFTPErrors())); } } } }
/** * (non-PHPDoc) * * @see \phpbu\App\Backup\Sync::sync() * @param \phpbu\App\Backup\Target $target * @param \phpbu\App\Result $result * @throws \phpbu\App\Backup\Sync\Exception */ public function sync(Target $target, Result $result) { // silence phpseclib $old = error_reporting(0); $sftp = new phpseclib\Net\SFTP($this->host); if (!$sftp->login($this->user, $this->password)) { error_reporting($old); throw new Exception(sprintf('authentication failed for %s@%s%s', $this->user, $this->host, empty($this->password) ? '' : ' with password ****')); } error_reporting($old); $remoteFilename = $target->getFilename(); $localFile = $target->getPathname(); if ('' !== $this->remotePath) { $remoteDirs = explode('/', $this->remotePath); foreach ($remoteDirs as $dir) { if (!$sftp->is_dir($dir)) { $result->debug(sprintf('creating remote dir \'%s\'', $dir)); $sftp->mkdir($dir); } $result->debug(sprintf('change to remote dir \'%s\'', $dir)); $sftp->chdir($dir); } } $result->debug(sprintf('store file \'%s\' as \'%s\'', $localFile, $remoteFilename)); $result->debug(sprintf('last error \'%s\'', $sftp->getLastSFTPError())); /** @noinspection PhpInternalEntityUsedInspection */ if (!$sftp->put($remoteFilename, $localFile, phpseclib\Net\SFTP::SOURCE_LOCAL_FILE)) { throw new Exception(sprintf('error uploading file: %s - %s', $localFile, $sftp->getLastSFTPError())); } }
/** * Executes the PushDbViaSsh Task. * * @return Robo\Result */ public function run() { // Login to the remote server $this->printTaskInfo('Logging into remote server - <info>ssh://' . $this->sshUser . '@' . $this->sshHost . '/</info>'); $ssh = new SFTP($this->sshHost); // Do we use password or a key if (file_exists($this->sshKey) && empty($this->sshPass)) { $key = new RSA(); $key->loadKey(file_get_contents($this->sshKey)); if (!$ssh->login($this->sshUser, $key)) { throw new RuntimeException('Failed to login via SSH using Key Based Auth.'); } } else { if (!$ssh->login($this->sshUser, $this->sshPass)) { throw new RuntimeException('Failed to login via SSH using Password Based Auth.'); } } // Create our dump filename $dump_name = tempnam(sys_get_temp_dir(), 'dump'); // Create our dump locally $cmd = 'mysqldump' . ' -h' . $this->localDbHost . ' -u' . $this->localDbUser . ' ' . (empty($this->localDbPass) ? '' : '-p' . $this->localDbPass) . ' ' . $this->localDbName . ' > ' . $dump_name; $this->printTaskInfo('Dumping db on local server - <info>' . $cmd . '</info>'); if (!$this->taskExec($cmd)->run()->wasSuccessful()) { throw new RuntimeException('Failed to create dump locally.' . 'HINT: Is the `mysqldump` binary in your "PATH"?'); } // Compress the dump $this->printTaskInfo('Compressing dump on local server - <info>' . $cmd . '</info>'); if ($fp_out = gzopen($dump_name . '.gz', 'wb9')) { if ($fp_in = fopen($dump_name, 'rb')) { while (!feof($fp_in)) { gzwrite($fp_out, fread($fp_in, 1024 * 512)); } fclose($fp_in); } else { throw new RuntimeException('Failed to open source dump file for reading.'); } gzclose($fp_out); } else { throw new RuntimeException('Failed to open destination compressed dump file for writing.'); } // Copy it up $this->printTaskInfo('Transfering dump to remote.'); $dump_name_remote = '/tmp/' . $this->remoteDbName . '-' . time() . '.sql'; if (!$ssh->put($dump_name_remote . '.gz', $dump_name, SFTP::SOURCE_LOCAL_FILE)) { throw new RuntimeException('Failed to upload db dump.'); } // Decompress dump on remote $cmd = 'gzip -d ' . $dump_name_remote . '.gz'; $this->printTaskInfo('Decompressing dump on remote server - <info>' . $cmd . '</info>'); $results = $ssh->exec($cmd); if ($ssh->getExitStatus() > 0) { throw new RuntimeException('Failed to decompress dump on remote.'); } // Import db remotely $cmd = 'mysql' . ' -h' . $this->remoteDbHost . ' -u' . $this->remoteDbUser . ' ' . (empty($this->remoteDbPass) ? '' : '-p' . $this->remoteDbPass) . ' ' . $this->remoteDbName . ' < ' . $dump_name_remote; $this->printTaskInfo('Importing dump remotely - <info>' . $cmd . '</info>'); $results = $ssh->exec($cmd); if ($ssh->getExitStatus() > 0) { throw new RuntimeException('Failed to import dump on remote.'); } // Delete dump from remote server $this->printTaskInfo('Removing dump from remote server. - <info>' . $dump_name_remote . '</info>'); if (!$ssh->delete($dump_name_remote)) { return Result::error($this, 'Failed to delete dump on remote.'); } // Remove the dump from the local server $this->printTaskInfo('Removing dump from local server. - <info>' . $dump_name . '</info>'); if (!unlink($dump_name)) { return Result::error($this, 'Failed to delete dump from local.'); } // If we get to here assume everything worked return Result::success($this); }
/** * sync local directory with ftp directory * * @param string $src * @param string $dst * @param callable|null $syncop * * @throws GlSyncFtpException */ public function syncDirectory($src, $dst, callable $syncop = null) { $this->login(); $files = []; $dirs = []; $this->getFiles($dst, "", $files, $dirs); // delete on ftp server, files not present in local directory foreach ($files as $name => $raw) { if (!file_exists($src . $name)) { $filepathFtp = $dst . strtr($name, ["\\" => "/"]); if ($syncop) { $syncop(self::DELETE_FILE, $filepathFtp); } $this->sftp->delete($filepathFtp); } } // delete on ftp server, unknowns directories $dirs = array_reverse($dirs); foreach ($dirs as $name => $raw) { if (!file_exists($src . $name)) { $filepathFtp = $dst . strtr($name, ["\\" => "/"]); if ($syncop) { $syncop(self::DELETE_DIR, $filepathFtp); } $this->sftp->rmdir($filepathFtp); } } // create new directories $finderdir = new Finder(); $finderdir->directories()->ignoreDotFiles(false)->followLinks()->in($src)->notName('.git*'); /** * @var SplFileInfo $dir */ foreach ($finderdir as $dir) { $dirpathFtp = $dst . "/" . strtr($dir->getRelativePathname(), ["\\" => "/"]); $stat = $this->sftp->stat($dirpathFtp); if (!$stat) { if ($syncop) { $syncop(self::CREATE_DIR, $dirpathFtp); } $this->sftp->mkdir($dirpathFtp, $dir->getRealPath(), SFTP::SOURCE_LOCAL_FILE); $this->sftp->chmod(0755, $dirpathFtp, $dir->getRealPath()); } } // copy new files or update if younger $finderdir = new Finder(); $finderdir->files()->ignoreDotFiles(false)->followLinks()->in($src)->notName('.git*'); /** * @var SplFileInfo $file */ foreach ($finderdir as $file) { $filepathFtp = $dst . "/" . strtr($file->getRelativePathname(), ["\\" => "/"]); $stat = $this->sftp->stat($filepathFtp); if (!$stat) { if ($syncop) { $syncop(self::NEW_FILE, $filepathFtp); } $this->sftp->put($filepathFtp, $file->getRealPath(), SFTP::SOURCE_LOCAL_FILE); } else { $size = $this->sftp->size($filepathFtp); if ($file->getMTime() > $stat['mtime'] || $file->getSize() != $size) { if ($syncop) { $syncop(self::UPDATE_FILE, $filepathFtp); } $this->sftp->put($filepathFtp, $file->getRealPath(), SFTP::SOURCE_LOCAL_FILE); } } } }
/** * Executes the SftpSync Task. * * @return Robo\Result */ public function run() { // Tell the world whats happening $this->printTaskInfo('Logging into server - ' . '<info>' . 'sftp://' . $this->sftpUser . ':' . (empty($this->sftpPass) ? $this->sftpKey : $this->sftpPass) . '@' . $this->sftpHost . '</info>'); // Intialise our sftp connection $sftp = new SFTP($this->sftpHost); // Do we use password or a key if (file_exists($this->sftpKey) && empty($this->sshPass)) { $key = new RSA(); $key->loadKey(file_get_contents($this->sshKey)); if (!$sftp->login($this->sshUser, $key)) { return Result::error($this, 'Failed to login via SFTP using Key Based Auth.'); } } else { if (!$sftp->login($this->sftpUser, $this->sftpPass)) { return Result::error($this, 'Failed to login via SFTP using Password Based Auth.'); } } // Check to see if a .htaccess file exists if ($sftp->stat($this->remotePath . '/.htaccess')) { // It does so lets rename it, just in case it messes with out helper script $this->printTaskInfo('Renaming .htaccess file'); if (!$sftp->rename($this->remotePath . '/.htaccess', $this->remotePath . '/disabled.htaccess')) { return Result::error($this, 'Failed to rename .htaccess file'); } } // Upload helper script $this->printTaskInfo('Uploading sftp helper script.'); if (!$sftp->put($this->remotePath . '/sftp-upload-helper.php', $this->sftp_upload_helper())) { return Result::error($this, 'UPLOAD OF HELPER SCRIPT FAILED'); } // Get the local and remote file arrays $this->printTaskInfo('Get a list of files on the local and remote servers.'); $local_files = $this->get_local_file_hashes($this->localPath); $remote_files = $this->get_remote_files(); // Delete helper script $this->printTaskInfo('Deleting sftp helper script.'); if (!$sftp->delete($this->remotePath . '/sftp-upload-helper.php')) { return Result::error($this, 'FAILED TO DELETE HELPER SCRIPT'); } // Rename htaccess file back if ($sftp->stat($this->remotePath . '/disabled.htaccess')) { // It does so lets rename it, just in case it messes with out helper script $this->printTaskInfo('Renaming .htaccess file back to original'); if (!$sftp->rename($this->remotePath . '/disabled.htaccess', $this->remotePath . '/.htaccess')) { return Result::error($this, 'Failed to rename .htaccess file back to original. OH SNAP... better fix this ASAP!'); } } $this->printTaskInfo('Comparing files between local and remote servers.'); // Create some arrays $files_to_ignore = []; $files_to_upload = []; $files_to_delete = []; $folders_to_create = []; $folders_to_delete = []; // Merge in our own ignores $files_to_ignore = array_merge($files_to_ignore, $this->ignore); // Remove any double ups in our ignore array $files_to_ignore = array_unique($files_to_ignore); // Remove a few extra items foreach ($files_to_ignore as $key => $value) { // We don't want to ignore the vendor dir if ($value == './vendor') { unset($files_to_ignore[$key]); } // We can't ignore everything if ($value == './') { unset($files_to_ignore[$key]); } } // Loop through the local files array looking for files that // don't exist or are different on the remote server. // ie: Files to upload foreach ($local_files as $path => $hash) { if (isset($remote_files[$path])) { if ($hash != $remote_files[$path]) { if (!in_array($path, $files_to_ignore)) { $files_to_upload[] = $path; } } } else { if (!in_array($path, $files_to_ignore)) { if ($hash == 'dir') { $folders_to_create[] = $path; } else { $files_to_upload[] = $path; } } } } // Loop through the remote files array looking for // files that don't exist on the local server. // ie: Files to delete foreach ($remote_files as $path => $hash) { if (!isset($local_files[$path])) { if (!in_array($path, $files_to_ignore)) { if ($hash == 'dir') { $folders_to_delete[] = $path; } else { $files_to_delete[] = $path; } } } } // We need to delete the children first $folders_to_delete = array_reverse($folders_to_delete); // Perform a double check of our files to ignore array foreach ($files_to_ignore as $path) { foreach ($files_to_upload as $key => $file) { if (strpos($file, $path) !== false) { unset($files_to_upload[$key]); } } foreach ($files_to_delete as $key => $file) { if (strpos($file, $path) !== false) { unset($files_to_delete[$key]); } } foreach ($folders_to_create as $key => $file) { if (strpos($file, $path) !== false) { unset($folders_to_create[$key]); } } foreach ($folders_to_delete as $key => $file) { if (strpos($file, $path) !== false) { unset($folders_to_delete[$key]); } } } // Check the dry run option if (!$this->dryRun) { // Create any needed folders foreach ($folders_to_create as $file) { $remotepath = str_replace('//', '/', $this->remotePath . substr($file, 1)); if (!$sftp->mkdir($remotepath)) { return Result::error($this, 'FAILED TO CREATE FOLDER: ' . $remotepath); } $this->printTaskInfo('Folder Created: ' . $file); } // Upload our files foreach ($files_to_upload as $file) { $this->printTaskInfo('Uploading: ' . $file); $localpath = str_replace('//', '/', $this->localPath . substr($file, 1)); $remotepath = str_replace('//', '/', $this->remotePath . substr($file, 1)); if (!$sftp->put($remotepath, $localpath, NET_SFTP_LOCAL_FILE)) { return Result::error($this, 'FAILED TO UPLOAD FILE: ' . $file); } } // Do we want to delete all the files? $delete_all = false; if (count($files_to_delete) > 0) { print_r($files_to_delete); do { $answer = $this->ask('Do you want to delete all these files? (yes|no)'); } while ($answer != 'yes' && $answer != 'no' && $answer != 'y' && $answer != 'n'); if ($answer == 'yes' || $answer == 'y') { $delete_all = true; } } // Loop through our files to delete. foreach ($files_to_delete as $file) { $remotepath = str_replace('//', '/', $this->remotePath . substr($file, 1)); if ($delete_all) { if (!$sftp->delete($remotepath)) { return Result::error($this, 'FAILED TO DELETE FILE: ' . $file); } else { $this->printTaskInfo('Deleted: ' . $file); } } else { do { $answer = $this->ask('Do you really want to delete? (yes|no)' . $remotepath); } while ($answer != 'yes' && $answer != 'no' && $answer != 'y' && $answer != 'n'); if ($answer == 'yes' || $answer == 'y') { if (!$sftp->delete($remotepath)) { return Result::error($this, 'FAILED TO DELETE FILE: ' . $file); } $this->printTaskInfo('Deleted: ' . $file); } } } // Same again but for folders $delete_all_folders = false; if (count($folders_to_delete) > 0) { print_r($folders_to_delete); do { $answer = $this->ask('Do you want to delete all these folders? (yes|no)'); } while ($answer != 'yes' && $answer != 'no' && $answer != 'y' && $answer != 'n'); if ($answer == 'yes' || $answer == 'y') { $delete_all_folders = true; } } foreach ($folders_to_delete as $file) { $remotepath = str_replace('//', '/', $this->remotePath . substr($file, 1)); if ($delete_all_folders) { if (!$sftp->rmdir($remotepath)) { return Result::error($this, 'FAILED TO DELETE FOLDER: ' . $file); } $this->printTaskInfo('Deleted Folder: ' . $file); } else { do { $answer = $this->ask('Do you really want to delete? (yes|no)' . $remotepath); } while ($answer != 'yes' && $answer != 'no' && $answer != 'y' && $answer != 'n'); if ($answer == 'yes' || $answer == 'y') { if (!$sftp->rmdir($remotepath)) { return Result::error($this, 'FAILED TO DELETE FOLDER: ' . $file); } $this->printTaskInfo('Deleted Folder: ' . $file); } } } $this->printTaskInfo('The remote server has been synced :)'); } else { $this->printTaskInfo('Files that would have been uploaded: '); print_r($files_to_upload); $this->printTaskInfo('Files that would have been deleted: '); print_r($files_to_delete); $this->printTaskInfo('Folders that would have been created: '); print_r($folders_to_create); $this->printTaskInfo('Folders that would have been deleted: '); print_r($folders_to_delete); } // If we get to here we assume everything worked return Result::success($this); }
/** * @param string $source * @param string $identifier * @return string */ public function uploadFile($source, $identifier) { return $this->sftp->put($identifier, $source, SFTP::SOURCE_LOCAL_FILE); }