Search code examples
javafile-uploadftpapache-commons-net

FTP list command throws MalformedServerReplyException: Truncated server reply


I have a Java application using Apache Commons Net to upload mp3 to my FTP server.

However, if it is a new file, it will throw a MalformedServerReplyException. If it is an existing file, it will upload and overwrite perfectly.

The exception is already thrown at line:

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

However, I checked in Wireshark and the command TYPE I goes fine.

Can someone help me with this?

Here an image of Wireshark up until the exception: enter image description here

public static void transferFile(File file, boolean OverwriteAllowed) {
    FtpLogin();
    try {
        System.out.println('\n');
        System.out.println("DEBUG: "+ file.toString());

        boolean isNewFile = false;
        String filePath = getFtpPathToMusic() + file.getName();

        ftpClient.sendNoOp();
        showServerReply();

        if (ftpClient.listFiles(filePath).length > 0) {
            System.out.println("File exists, and overwrite allowed is: " + OverwriteAllowed);
        } else {
            isNewFile = true;
          //  System.out.println("File does not exist yet on server");
        }

        if (OverwriteAllowed || isNewFile) {
            ftpClient.setStrictReplyParsing(false);
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            showServerReply();
            InputStream inputStream = new FileInputStream(file);


            OutputStream outputStream = ftpClient.storeFileStream(filePath);
            byte[] bytesIn = new byte[4096];
            int read;
            long remaining = file.length();
            long transferred = 0;

            System.out.println("Transfering data...");
            while ((read = inputStream.read(bytesIn)) != -1) {
                outputStream.write(bytesIn, 0, read);
                remaining -= read;
                transferred += read;
                System.out.print('\r');
                System.out.print("Remaining: " + remaining/1024 + "kb | Transferred: " + transferred/1024 + "kb");
            }
            System.out.println();
            inputStream.close();
            outputStream.close();

            boolean completed = ftpClient.completePendingCommand();
            if (completed) {
                showServerReply();
                System.out.println("File " + filePath + " uploaded succesfully");
            }
        } else {
            System.out.println("File is skipped");
        }
    } catch (IOException e) {
        e.printStackTrace();
        showServerReply();
    }

}

Expected: successful upload
Actual: MalformedServerReplyException

org.apache.commons.net.MalformedServerReplyException: Truncated server reply: 
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:332)
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:300)
at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:523)
at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:648)
at org.apache.commons.net.ftp.FTP.type(FTP.java:1119)
at org.apache.commons.net.ftp.FTPClient.setFileType(FTPClient.java:1559)
at FtpSupport.FtpTransfer.transferFile(FtpTransfer.java:116)
at Home.ConverterGuiHome$convertMp3FilesExecute.actionPerformed(ConverterGuiHome.java:144)

At request - the full (FTP) logging:

Getting files from: /ideaProjects/GsmMp3Manager/src/main/Mp3Files/export
Creating mp3 object from file: 377 test.mp3
220 DiskStation FTP server ready.
SERVER: 220 DiskStation FTP server ready.
NOOP
200 NOOP command successful.
SERVER: 200 NOOP command successful.
USER *******
331 Password required for Barbet.
PASS *******
230 User Barbet logged in.
SERVER: 230 User Barbet logged in.
LOGGED IN SERVER
File listing in directory  :
SYST
215 UNIX Type: L8
PASV
227 Entering Passive Mode (77,164,214,202,216,242)
LIST 
150 Opening BINARY mode data connection for 'file list'.
226 Transfer complete.
[home]      4096        2018-12-12 00:00:00
[Spotlight]     4096        2018-11-17 00:00:00
[music]     4096        2018-11-22 00:00:00
[Mission Possible]      4096        2013-11-13 00:00:00
DEBUG:377 test.mp3


DEBUG: src/main/Mp3Files/export/377 test.mp3
NOOP
200 NOOP command successful.
SERVER: 200 NOOP command successful.
PASV
227 Entering Passive Mode (77,164,214,202,216,241)
LIST /Spotlight/muziek/377 test.mp3
150 Opening BINARY mode data connection for 'file list'.
550 /Spotlight/muziek/377 test.mp3: No such file or directory.
TYPE I
org.apache.commons.net.MalformedServerReplyException: Truncated server reply: 
    at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:332)
    (... see stack trace)

 Close ftp session
QUIT
200 Type set to I.
SERVER: 200 Type set to I.

Solution

  • It would have to be confirmed by a full Wireshark dump, but I believe the log file indicates that the 550 response to LIST command is followed by two newlines. The Apache FTPClient treats the second "line" as an (invalid) response to the following TYPE I command. So it looks like a server-side bug.

    Did you try using other method to check for a file existence?
    See my answer to Checking file existence on FTP server
    (as the answer says, using listFiles to check for the file existence is actually a violation of FTP protocol).