Search code examples
javainputstreamftp-client

Apache FTPClient.retrieveFileStream(String) returns null


I am using Java 11 and SpringBoot. I am trying to create a FTPClient to read files from an existing FTP server. Using Apache FTPClient.

Problem:

InputStream is = ftp.retrieveFileStream(file.getName());

The following always returns a null InputStream.

Info:

logger.info("File name: "+file.getName()+", type: "+file.getType()+", size: "+file.getSize()+".");

returns:

File name: cam_test, type: 1, size: 28.

Question:

You can see that there is a file called 'cam_test', why can't this be converted into an InputStream?

Code:

import org.apache.commons.net.ftp.FTPClient;

public void processFiles() {
    FTPClient ftp = new FTPClient();
    try {
        ftp.connect(IP_ADDRESS);

        int reply = ftp.getReplyCode();

        logger.info("Connected to " + IP_ADDRESS + ". ReplyCode: '"+reply+"'.");
        if(!FTPReply.isPositiveCompletion(reply)) {
            ftp.disconnect();
            logger.error("FTP server ('"+IP_ADDRESS+"') refused connection.");
        } else {
            // transfer files
            ftp.login(USERNAME, PASSWORD);
            FTPFile[] files = ftp.listFiles(BASE_DIR);
            logger.info("Connected to " + IP_ADDRESS + ". Got '"+files.length+"' files from working directory: "+ftp.printWorkingDirectory()+BASE_DIR+".");
            for (FTPFile file : files) {
                logger.info("File name: '"+file.getName()+"', type: '"+file.getType()+"', size: '"+file.getSize()+"', directory: '"+file.isDirectory()+"', file: '"+file.isFile()+"'.");
                if (file.isFile() && 0 == file.getType()) {
                    InputStream is = ftp.retrieveFileStream(file.getName());  // <--- is always null
                    processFile(file, is);
                    if (is != null) {
                        is.close();
                    }
                    boolean completePendingCommand = ftp.completePendingCommand();
                    logger.info("completePendingCommand: "+completePendingCommand);
                }
            }
        }
    } catch(IOException e) {
        logger.error(e.getMessage(), e);
    } finally {
        if(ftp.isConnected()) {
            try {
                ftp.disconnect();
            } catch(IOException ioe) {
                // do nothing
            }
        }
    }
}

Solution

  • You must add completePendingCommand after each command.

    In the following piece of code completePendingCommand is commented out.

            for (FTPFile file : files) {
              System.out.println(
                  "File name: " + file.getName() + ", type: " + file.getType() + ", size: " + file.getSize() + ".");
              InputStream is = ftp.retrieveFileStream(file.getName());
    
              System.out.println(is == null);
    
    //          ftp.completePendingCommand();
            }
    

    The result is:

    Connected to ftp.dlptest.com. 220

    File name: actorstoday.txt, type: 0, size: 0. false

    File name: actorstomorrow.txt, type: 0, size: 0. true

    As you an see the second request is returning a null InputStream.

    Changing to:

    for (FTPFile file : files) {
      System.out.println(
          "File name: " + file.getName() + ", type: " + file.getType() + ", size: " + file.getSize() + ".");
      InputStream is = ftp.retrieveFileStream(file.getName());
    
      System.out.println(is == null);
    
      ftp.completePendingCommand();
    }
    

    The result is :

    Connected to ftp.dlptest.com. 220

    File name: actorstoday.txt, type: 0, size: 0. false

    File name: actorstomorrow.txt, type: 0, size: 0. false

    In each iteration of the for loop you must call completePendingCommand.