Slim 4 - League Flysystem v2 SFTP
source link: https://odan.github.io/2021/01/03/slim4-sftp.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Daniel Opitz - Blog
Developer, Trainer, Open Source Contributor
Blog About me DonateSlim 4 - League Flysystem v2 SFTP
03 Jan 2021
Table of contents
Requirements
- PHP 7.3+
- A Slim 4 application
Introduction
The HTTP protocol is great for transferring small amounts of data very quickly. That’s why most people prefer RESTful APIs for communication between servers.
You have to distinguish between small amounts of data that are transferred immediately and large amounts of data that are transferred with a time delay.
HTTP works very well as long as the amount of data is very small (< 5 MB) and there are no network timeouts.
In some rare use cases you may need to transfer more than 5 MB at once over the wire in a more delayed fashion, for example once a day or so. Then it would make sense to think about a specialized “file transfer protocol”, like SFTP (FTP over SSH).
SFTP or Secure File Transfer Protocol is also known as SSH File Transfer Protocol. It is a network protocol to be able to transfer files to remote systems.
SFTP allows companies to securely transfer billing and financial data or files for disaster recovery, for example. SFTP relies on SSH (Secure Shell) to transfer data. The client must authenticate itself to the server. Commands and data are encrypted. In this way, passwords and other sensitive information are not sent over the network in plain text and thus cannot be read or sniffed out.
SFTP was developed by the IETF (Internet Engineering Task Force) to allow files to be transferred and managed securely over TCP/IP networks.
SFTP uses the same commands as the traditional File Transfer Protocol (FTP).
Installation
The Flysystem SFTP Adapter provides a powerful filesystem and SFTP abstraction and uses Phpseclib to provide a convenient interface for SFTP file transfers.
To install Flysystem, run:
composer require league/flysystem
Before using the SFTP drivers, you will need to install the appropriate package via the Composer package manager:
composer require league/flysystem-sftp
Configuration
If you need to configure a SFTP filesystem, you may use the configuration example below:
use League\Flysystem\PhpseclibV2\SftpAdapter;
use League\Flysystem\PhpseclibV2\SftpConnectionProvider;
use League\Flysystem\UnixVisibility\PortableVisibilityConverter;
// ...
$settings['sftp'] = [
'adapter' => new SftpAdapter(
new SftpConnectionProvider(
'localhost',
'username',
'password',
),
'/', // remote root path
PortableVisibilityConverter::fromArray(
[
'file' => [
'public' => 0640,
'private' => 0604,
],
'dir' => [
'public' => 0740,
'private' => 7604,
],
]
)
),
];
Container Setup
For autowiring I want to give the container a unique class name, because
I my projects I have multiple Filesystem adapters e.g. one for the local filesystem
and multiple SFTP adapters for other different servers.
For this reason I extend a new class from \League\Flysystem\Filesystem
.
Then I add a container definition for that extended class,
instead of using the too generic \League\Flysystem\Filesystem
class.
This allows you to explicitly declare the connection within the (service) class
constructor and makes it possible to handle multiple different Filesystem
“drivers” as simple as possible.
First create a new class in, src/Filesystem/SftpFilesystem.php
.
<?php
namespace App\Filesystem;
use League\Flysystem\Filesystem;
final class SftpFilesystem extends Filesystem
{
// must be empty
}
You could also give the class a less-generic name.
For example when you have multiple “clients” you could give them names
like AcmeSftpFilesystem
, ContosoSftpFilesystem
etc.
Insert a DI container definition for the SftpFilesystem:class
in config/container.php
:
<?php
use App\Filesystem\SftpFilesystem;
use League\Flysystem\Filesystem;
use Psr\Container\ContainerInterface;
// ...
return [
// ...
SftpFilesystem::class => function (ContainerInterface $container) {
$sftp = $container->get('settings')['sftp'];
return new SftpFilesystem($sftp['adapter']);
},
];
Usage
To get the SftpFilesystem
instance via dependency injection, just declare it in
the constructor where you need it. Normally you should use the filesystem instance
only within a domain or application service.
Example
<?php
namespace App\Domain\Example\Service;
use App\Filesystem\SftpFilesystem;
final class Example
{
private SftpFilesystem $sftpFilesystem;
public function __construct(SftpFilesystem $filesystem)
{
$this->sftpFilesystem = $filesystem;
}
public function foo(): void
{
// Reading a remote file
$content = $this->sftpFilesystem->read('index.html');
// ...
}
}
Downloading (reading) files
Like writing a file, reading a file can be done in two ways. You can read the file contents in full as a string, or “stream” it by obtaining a resource. Using the resource allows you to stream the contents to a destination (local or to another filesystem) in order to keep memory usage low.
$content = $this->sftpFilesystem->read('index.html');
Uploading (writing) files
$this->sftpFilesystem->write('test.html', 'test');
List (remote) files
use League\Flysystem\StorageAttributes;
use League\Flysystem\FileAttributes;
use League\Flysystem\DirectoryAttributes;
// ...
/** @var StorageAttributes $item */
$items = $this->sftpFilesystem->listContents('/');
foreach ($items as $item) {
$path = $item->path();
if ($item instanceof FileAttributes) {
// handle the file
}
if ($item instanceof DirectoryAttributes) {
// handle the directory
}
}
For more information about the usage, check out the Filesystem API documentation.
Conclusion
We have learned that, with a little trick, it’s very easy to use the league/flysystem
package with multiple different Filesystem “drivers” in combination with an
autowired DI container and dependency injection.
Read more
© 2021 Daniel Opitz | Twitter
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK