league/flysystem-sftp
Deprecated since Flysystem 3.0; use flysystem-sftp-v3 instead. Provides an SFTP adapter for Flysystem using phpseclib2. This is a sub-split—issues and PRs belong in the main Flysystem repo. Install via composer require league/flysystem-sftp.
Installation
composer require league/flysystem-sftp
Ensure league/flysystem is also installed (dependency).
Basic Usage
use League\Flysystem\Filesystem;
use League\Flysystem\Sftp\SftpAdapter;
$adapter = new SftpAdapter(
'sftp.example.com',
22,
'username',
'password',
'/remote/path'
);
$filesystem = new Filesystem($adapter);
First Use Case: Upload a File
$filesystem->write('local-file.txt', 'Hello, SFTP!');
Where to Look First
SftpAdapter constructor and set*() methods for configuration.Dynamic Connection Handling
Use dependency injection (e.g., Laravel’s config()) for credentials:
$adapter = new SftpAdapter(
config('sftp.host'),
config('sftp.port'),
config('sftp.username'),
config('sftp.password'),
config('sftp.root')
);
Streaming Large Files Leverage Flysystem’s streaming API to avoid memory issues:
$filesystem->writeStream('large-file.zip', fopen('local.zip', 'r'));
Directory Operations
// Create a directory
$filesystem->createDirectory('new-folder');
// List files
$contents = $filesystem->listContents('remote/path');
Temporary Files
Use write() + delete() for atomic operations:
$filesystem->write('temp.txt', $data);
// Process file...
$filesystem->delete('temp.txt');
Laravel Storage Integration
Extend Filesystem in a custom driver:
// app/Providers/FlysystemServiceProvider.php
public function register()
{
Storage::extend('sftp', function ($app, $config) {
$adapter = new SftpAdapter(
$config['host'],
$config['port'],
$config['username'],
$config['password'],
$config['root']
);
return new Filesystem($adapter);
});
}
Configure in config/filesystems.php:
'disks' => [
'sftp' => [
'driver' => 'sftp',
'host' => env('SFTP_HOST'),
'port' => env('SFTP_PORT', 22),
// ...
],
];
Retry Logic for Failures
Wrap operations in a retry loop (e.g., using spatie/laravel-retryable):
use Retryable;
class SftpUploader {
use Retryable;
public function upload($path, $contents)
{
retry(5, function () use ($path, $contents) {
$filesystem->write($path, $contents);
}, function ($e) {
return $e instanceof \League\Flysystem\Sftp\Exception\ConnectionException;
});
}
}
SSH Key Authentication
Use setSshKeyPath() for key-based auth:
$adapter->setSshKeyPath('/path/to/private_key');
Connection Timeouts
$adapter->setTimeout(10); // 10 seconds
$adapter->setSshConnectionOptions([
'verbose' => STDERR,
]);
Permission Denied
Permission denied errors often stem from incorrect remote paths or user permissions.chmod/chown on the server).root path in the adapter ends with / (e.g., /home/user/).Passive Mode
$adapter->setSshConnectionOptions([
'passive_mode' => true,
]);
File Locking
write() + rename()):
$filesystem->write('temp.txt', $data);
$filesystem->rename('temp.txt', 'final.txt');
$adapter->setSshConnectionOptions([
'verbose' => STDERR,
]);
phpseclib (used internally) may trigger deprecation warnings. Update:
composer require phpseclib/phpseclib:^3.0
Custom SSH Options
Pass additional phpseclib options:
$adapter->setSshConnectionOptions([
'timeout' => 30,
'compression' => 'zlib',
]);
Event Listeners Extend the adapter to log operations:
$adapter->addListener('preWrite', function ($event) {
logger()->debug('Writing to SFTP', ['path' => $event->getPath()]);
});
Fallback to Local Storage Implement a hybrid storage system:
$filesystem = new Filesystem(new CacheAdapter(
new SftpAdapter(...),
new LocalAdapter(new Filesystem())
));
22. Omit it if using the standard port../file → /remote/path/file). Ensure your logic accounts for this..env or a secrets manager.How can I help you explore Laravel packages today?