In this example we will demonstrate anFTP example program written in Java using some of theNIO features available to us.
The example program will take the form of a command line program which accepts 2 arguments, namely theFTP location to transfer the file from and the local destination on the file system, inclusive of the file name, of where to save the file.
We will configure our local operating system to serve a specific directory viaFTP. In order to simulate theFTP server we will make use of the vsftpd ubuntu package.
1. Introduction
In this example we make use of aURL object to specify theFTP location (including authentication credentials).
A FileChannel is used for writing the contents of the file to local disk, by calling one of the open(..)methods of the FileChannel class.
We provide thePath to theFile and indicate theStandardOpenOption#WRITE andStandardOpenOption#CREATE modes when opening.
We also make use of a ReadableByteChannel to open aChannel to theFTP location and read the contents untill end.
2. Technologies used
The example code in this article was built and run using:
- Java 8
- Maven 3.3.9
- STS (3.9.0.RELEASE)
- Ubuntu 16.04
- vsftpd (package)
3. Setup
To ensure that Maven and Java are installed you can execute the following:
Confirm Java and Maven
java -versionjava version "1.8.0_101"Java(TM) SE Runtime Environment (build 1.8.0_101-b13)Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)mvn -versionApache Maven 3.3.9Maven home: /usr/share/mavenJava version: 1.8.0_101, vendor: Oracle CorporationJava home: /home/jean-jay/runtimes/jdk1.8.0_101/jreDefault locale: en_ZA, platform encoding: UTF-8OS name: "linux", version: "4.10.0-42-generic", arch: "amd64", family: "unix"
4. Setting up an FTP server
To setup a local FTP server we will make use ofvsftpd. If not already setup we can install and configure it via the command line:
Installing vsftpd
# Install vsftpdsudo apt-get updatesudo apt-get install vsftpd# Backup configurationsudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig# Ensure firewall inactivesudo systemctl stop ufw# Setup ftp configurationsudo vim /etc/vsftpd.conf # Ensure the following settings are present anonymous_enable=NO local_enable=YES userlist_enable=YES userlist_file=/etc/vsftpd.userlist userlist_deny=NO# Save the file# Add current user to userlistecho jean-jay | sudo tee -a /etc/vsftpd.userlist# Restart servicesudo systemctl restart vsftpd# Test itftp -p localhostConnected to localhost.220 (vsFTPd 3.0.3)Name (localhost:jean-jay): 331 Please specify the password.Password:230 Login successful.Remote system type is UNIX.Using binary mode to transfer files.ftp
5. The Code
The 3 core classes in the program includeNIOftp,FileReader andFileWriter.
NIOftp
public final class NIOftp { private static final int FTP_BUFFER_CAPACITY = 2048; private NIOftp() { throw new IllegalStateException(Constants.INSTANTIATION_NOT_ALLOWED); } public static void ftp(final URL from, final String target) throws IOException { if (Objects.isNull(from)) { throw new IllegalArgumentException("URL required for ftp source"); } if (StringUtils.isBlank(target)) { throw new IllegalArgumentException("target required"); } final FileReader reader = createReader(from); final FileWriter writer = createWriter(target); try { System.out.printf("Starting ftp from %s\n", from.toString()); ByteBuffer buffer = ByteBuffer.allocate(FTP_BUFFER_CAPACITY); while (reader.read(buffer) >= 0) { writer.write((ByteBuffer) buffer.flip()); buffer.clear(); } } finally { System.out.println("Completed transfer"); reader.close(); writer.close(); } } private static FileReader createReader(final URL from) throws IOException { assert !Objects.isNull(from); return new FileReader(from); } private static FileWriter createWriter(final String target) throws IOException { assert StringUtils.isNotBlank(target); return new FileWriter(target); }}- lines 18-19: we create the
FileReaderandFileWriterinstances respectively - lines 21-35: we allocate aByteBuffer and read the content from theFTP location into saidByteBuffer. We then
fliptheByteBuffer to prepare it for reading and delegate that task on to theFileWriter. TheByteBuffer is then cleared for the next iteration.
FileReader

Thank you!
We will contact you soon.
final class FileReader { private final ReadableByteChannel from; FileReader(final URL url) throws IOException { this.from = Channels.newChannel(url.openStream()); } int read(final ByteBuffer buffer) throws IOException { return this.from.read(buffer); } void close() throws IOException { Objects.requireNonNull(this.from).close(); }}- The
FileReaderencapsulates the reading of the remote file.
FileWriter
final class FileWriter { private final FileChannel target; FileWriter(final String path) throws IOException { this.target = FileChannel.open(Paths.get(path), StandardOpenOption.WRITE, StandardOpenOption.CREATE); } void write(final ByteBuffer buffer) throws IOException { this.target.write(buffer); while (buffer.hasRemaining()) { buffer.compact(); this.target.write(buffer); } } void close() throws IOException { Objects.requireNonNull(this.target).close(); }}- The
FileWriterencapsulates the writing of the file to local file system
6. Running the Program
Ensurevsftpd is running
Check status of vsftpd
sudo systemctl status vsftpd[sudo] password for jean-jay: vsftpd.service - vsftpd FTP server Loaded: loaded (/lib/systemd/system/vsftpd.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2017-12-23 06:15:22 CET; 7h ago Process: 1210 ExecStartPre=/bin/mkdir -p /var/run/vsftpd/empty (code=exited, status=0/SUCCESS) Main PID: 1222 (vsftpd) Tasks: 1 Memory: 2.3M CPU: 150ms CGroup: /system.slice/vsftpd.service └─1222 /usr/sbin/vsftpd /etc/vsftpd.conf
Then navigate to the home directory of the current user, on my system that would be/home/jean-jay.
Then place a file that you would like to ftp in that location eg:docs.zip as this is the folder thatvsftpd will be serving.
Then navigate to the root folder of where you downloaded the example project. Executemvn clean install package and then navigate into thetarget folder of said project. Once there execute the following:
Running program (replace username and password with proper values)
java -jar nio_ftp_example-0.0.1-SNAPSHOT.jar -u ftp://<username>:<password>@localhost/docs.zip -t /home/jean-jay/Documents/github-projects/codegeeks/nio-ftp-example/target/docs.zip Starting ftp from ftp://<username>:<password>@localhost/docs.zipCompleted transfer
You can then confirm your ftp by checking the file in yourtargetfolder.
7. Summary
In this example we briefly covered some of the core abstractions used in making this example. We also demonstrated the use of said example program toFTP a file from a localFTP server serving a directory from our file system.
8. Download the Source Code
This was a Java Nio FTP Example.
You can download the full source code of this example here:Java Nio FTP Example

Thank you!
We will contact you soon.



