javasocketsubuntuftpapache-commons-net

SocketException: Connection reset while FTP upload


I am trying to upload a file to an FTP server.
This is my code:

FTPClient ftpClient = new FTPClient();
try {
    List<PoiCmsRule> appPois = getAllRules();
    try (FileWriter writer = new FileWriter(backupFile)) {
        new Gson().toJson(backupData, writer);
    }
    try (FileInputStream fis = new FileInputStream(backupFile)) {
        ftpClient.connect(host);
        ftpClient.login(login, password);
        ftpClient.storeFile("backup.json", fis);
        ftpClient.logout();
    }
} catch (Exception e) {
    log.error(e.getMessage(), e);
} finally {
    try {
        ftpClient.disconnect();
    } catch (IOException e) {
        log.error(e.getMessage(), e);
    }
}

And it works perfectly fine when I run this on localhost. But when I run in on server I get this exception:

Caused by: java.net.SocketException: Connection reset
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
    at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)

I think it indicates I might have some problems with the firewall or proxy.

This is a Spring Boot app run on the Ubuntu server with Nginx as a proxy.

How can I find what is causing this exception?


Logs from a successful connection with command-line ftp in passive mode:

ubuntu@ip-server:~$ ftp -p -d my_host
Connected to my_host
220 FTP-Server
ftp: setsockopt: Bad file descriptor
Name (my_host): username
---> USER username
331 Please specify the password.
Password:
---> PASS XXXX
230 Login successful.
---> SYST
215 UNIX Type: L8
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
ftp: setsockopt (ignored): Permission denied
---> PASV
227 Entering Passive Mode (153,92,207,128,127,65)
---> LIST
150 Here comes the directory listing.
// file list
226 Directory send OK.
ftp>

Solution

  • Apache Commons Net FTPClient defaults to the FTP active mode. The active mode hardly ever works these days due to ubiquitous firewalls and NATs (for details, see my article on FTP active/passive connection modes).

    To switch FTPClient to the passive mode, call FTPClient.enterLocalPassiveMode somewhere after FTPClient.connect:

    ftpClient.connect(host);
    ftpClient.login(login, password);
    ftpClient.enterLocalPassiveMode();