FTP Connector
The FTP connector provides Akka Stream sources to connect to FTP, FTPs and SFTP servers. Currently, two kinds of sources are provided:
- one for browsing or traversing the server recursively and,
- another for retrieving files as a stream of bytes.
Artifacts
- sbt
libraryDependencies += "com.lightbend.akka" %% "akka-stream-alpakka-ftp" % "0.15"
- Maven
<dependency> <groupId>com.lightbend.akka</groupId> <artifactId>akka-stream-alpakka-ftp_2.12</artifactId> <version>0.15</version> </dependency>
- Gradle
dependencies { compile group: 'com.lightbend.akka', name: 'akka-stream-alpakka-ftp_2.12', version: '0.15' }
Usage
Configuring the connection settings
In order to establish a connection with the remote server, you need to provide a specialized version of a RemoteFileSettings instance. It’s specialized as it depends on the kind of server you’re connecting to: FTP, FTPs or SFTP.
- Scala
-
import akka.stream.alpakka.ftp.FtpCredentials.AnonFtpCredentials import java.net.InetAddress val settings = FtpSettings( InetAddress.getByName("localhost"), credentials = AnonFtpCredentials, binary = true, passiveMode = true )
- Java
-
import akka.stream.alpakka.ftp.FtpCredentials; import akka.stream.alpakka.ftp.FtpSettings; import java.net.InetAddress; import java.net.UnknownHostException; public class FtpSettingsExample { private FtpSettings settings; public FtpSettingsExample() { try { settings = new FtpSettings( InetAddress.getByName("localhost"), FtpSettings.DefaultFtpPort(), FtpCredentials.createAnonCredentials(), false, // binary true // passiveMode ); } catch (UnknownHostException e) { e.printStackTrace(); } } }
The configuration above will create an anonymous connection with a remote FTP server in passive mode. For both FTPs and SFTP servers, you will need to provide the specialized versions of these settings: FtpsSettings or SftpSettings respectively.
For non-anonymous connection, please provide an instance of NonAnonFtpCredentials instead.
For connection using a private key, please provide an instance of SftpIdentity to SftpSettings.
Traversing a remote FTP folder recursively
In order to traverse a remote folder recursively, you need to use the ls
method in the FTP API:
- Scala
-
import akka.NotUsed import akka.stream.alpakka.ftp.scaladsl.Ftp import akka.stream.scaladsl.Source def listFiles(basePath: String, settings: FtpSettings): Source[FtpFile, NotUsed] = Ftp.ls(basePath, settings)
- Java
-
import akka.NotUsed; import akka.stream.alpakka.ftp.FtpFile; import akka.stream.alpakka.ftp.FtpSettings; import akka.stream.alpakka.ftp.javadsl.Ftp; import akka.stream.javadsl.Source; public class FtpTraversingExample { public Source<FtpFile, NotUsed> listFiles(String basePath, FtpSettings settings) throws Exception { return Ftp.ls(basePath, settings); } }
Source on Github Source on Github
This source will emit FtpFile elements with no significant materialization.
For both FTPs and SFTP servers, you will need to use the FTPs
and SFTP
API respectively.
Retrieving files
In order to retrieve a remote file as a stream of bytes, you need to use the fromPath
method in the FTP API:
- Scala
-
import akka.stream.IOResult import akka.stream.alpakka.ftp.scaladsl.Ftp import akka.stream.scaladsl.Source import akka.util.ByteString import scala.concurrent.Future def retrieveFromPath(path: String, settings: FtpSettings): Source[ByteString, Future[IOResult]] = Ftp.fromPath(path, settings)
- Java
-
import akka.stream.IOResult; import akka.stream.alpakka.ftp.FtpSettings; import akka.stream.alpakka.ftp.javadsl.Ftp; import akka.stream.javadsl.Source; import akka.util.ByteString; import java.util.concurrent.CompletionStage; public class FtpRetrievingExample { public Source<ByteString, CompletionStage<IOResult>> retrieveFromPath(String path, FtpSettings settings) throws Exception { return Ftp.fromPath(path, settings); } }
Source on Github Source on Github
This source will emit ByteString elements and materializes to Future in Scala API and CompletionStage in Java API of IOResult when the stream finishes.
For both FTPs and SFTP servers, you will need to use the FTPs
and SFTP
API respectively.
Writing files
In order to store a remote file from a stream of bytes, you need to use the toPath
method in the FTP API:
- Scala
-
import akka.stream.IOResult import akka.stream.alpakka.ftp.scaladsl.Ftp import akka.stream.scaladsl.Sink import akka.util.ByteString import scala.concurrent.Future def storeToPath(path: String, settings: FtpSettings, append: Boolean): Sink[ByteString, Future[IOResult]] = Ftp.toPath(path, settings, append)
- Java
-
import akka.stream.IOResult; import akka.stream.alpakka.ftp.FtpSettings; import akka.stream.alpakka.ftp.javadsl.Ftp; import akka.stream.javadsl.Sink; import akka.util.ByteString; import java.util.concurrent.CompletionStage; public class FtpWritingExample { public Sink<ByteString, CompletionStage<IOResult>> storeToPath(String path, FtpSettings settings) throws Exception { return Ftp.toPath(path, settings); } }
Source on Github Source on Github
This sink will consume ByteString elements and materializes to Future in Scala API and CompletionStage in Java API of IOResult when the stream finishes.
For both FTPs and SFTP servers, you will need to use the FTPs
and SFTP
API respectively.
Running the example code
The code in this guide is part of runnable tests of this project. You are welcome to browse the code, edit and run it in sbt.
- Scala
-
sbt > ftp/test
- Java
-
sbt > ftp/test
When using the SFTP
API, take into account that JVM relies on /dev/random
for random number generation by default. This might potentially block the process on some operating systems as /dev/random
waits for a certain amount of entropy to be generated on the host machine before returning a result. In such case, please consider providing the parameter -Djava.security.egd = file:/dev/./urandom
into the execution context. Further information can be found here.