0

I am using org.apache.commons.net.ftp.FTPSClient to upload file to FTPS server (over TLS/SSL).

Note the FTP server lies on Windows server, and the certificate is a self-signed one, which can be connected and have files uploaded successfully via FileZilla after I accepted the warning that the certificate is not valid.

However the java code handling the same stuff doesn't work. I have checked the connect step and loggin step separately in code, and found the error happened after connect step (ftps.connect(server,port)) - the log "Connected to server:port" has been printed in console. I am confused that getRemoteAddress should be handled during connect step, which has already completed.

String ftpsServer = "host";
    int ftpsPort = 21;
    String ftpsUser = "domain\username";
    String ftpsPass = "password";

    try{
        FTPSClient ftpClient = new FTPSClient();
        ftpClient.connect(ftpsServer,ftpsPort);
        // check FTP connection
        int reply = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)){
            ftpClient.disconnect();
            System.err.println("FTP server refused connection.");
            System.exit(1);
            } else {
                System.out.println("Connected to " + ftpsServer + ":" + ftpsPort + ".");
            }
        // check FTP login
        if (ftpClient.login(ftpsUser, ftpsPass)){
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            System.out.println("Logged into FTP server successfully");
        } else {
            System.out.println("Failed log into FTP server");
            ftpClient.logout();
            ftpClient.disconnect();
        }

        File localFile = new File("C:/test/history.txt");
        InputStream inputStream = new FileInputStream(localFile);
        boolean uploaded = ftpClient.storeFile("/wwwroot/preview/history.txt", inputStream);
        System.out.println("uploaded successful? " + uploaded);

        inputStream.close();
        ftpClient.logout();
        ftpClient.disconnect();

    }catch(Exception e){
        LOG.error("Exception when merging Reminderlist is: ", e);

    }

The full log printed in console is :

Connected to 10.20.254.xx:21.
Failed log into FTP server
ERROR 2017-10-13 15:27:15,322 [main] 
com.redwood.contentmanagement.UnzipFiles: Exception when merging 
Reminderlist is: 
java.lang.NullPointerException
at 
org.apache.commons.net.SocketClient.getRemoteAddress(SocketClient.java:553) ~[commons-net-2.2.jar:2.2]
at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:509) ~[commons-net-2.2.jar:2.2]
at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:425) ~[commons-net-2.2.jar:2.2]
at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:1548) ~[commons-net-2.2.jar:2.2]
at com.redwood.contentmanagement.TransferOverFTPS.myTransform(TransferOverFTPS.java:55) ~[classes/:?]
at com.redwood.contentmanagement.TransferOverFTPS.main(TransferOverFTPS.java:110) ~[classes/:?]

Thanks a lot for @devpuh's reply, I have logged in successfully after changing \ to / in username, but still failed uploading the file, and there was no detailed information where failed, below is the full log in console:

Connected to 10.20.254.10:21.
Logged into FTP server successfully
uploaded successful? false
James Z
  • 12,209
  • 10
  • 24
  • 44
Robert
  • 17
  • 3
  • 8
  • share the entire code of TransferOverFTPS.java – Jaydeep Rajput Oct 13 '17 at 08:49
  • The code is function myTransform(), and only main function not pasted: public static void main(String[] args) { TransferOverFTPS test = new TransferOverFTPS(); test.myTransform(); } – Robert Oct 13 '17 at 08:57
  • Are you sure that the last output is `Connected to ...` and not `Failed log into FTP server`, it seems like the ftpClient is closed –  Oct 13 '17 at 09:08
  • @Robert have a look at "How do I debug FTP applications" https://stackoverflow.com/a/13305674/8097737 this will help you to find out what went wrong –  Oct 13 '17 at 09:58
  • `_openDataConnection_` is trying to open the data connection, which occurs after (possibly long after) opening the control connection. And it's actually calling `getRemoteAddr()` solely to check the _type_ of address returned to decide whether to do some IPv6-related stuff. (As devpuh said) Are you sure your code _didn't_ take the login-failed path? – dave_thompson_085 Oct 13 '17 at 10:10

1 Answers1

0

For the original question

Your login credentials are incorrect, but you are still trying to upload the file.

You must handle the incorrect login proper. For example:

// check FTP login
if (ftpClient.login(ftpsUser, ftpsPass)){
    ftpClient.enterLocalPassiveMode();
    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    System.out.println("Logged into FTP server successfully");
} else {
    System.out.println("Failed log into FTP server");
    ftpClient.logout();
    ftpClient.disconnect();
    return;
}

For the edited question

To find out why the upload doesn't work you can get last reply from the Server with getReplyString(). For example:

boolean uploaded = ftpClient.storeFile("/wwwroot/preview/history.txt", inputStream);
if(!uploaded) {
    System.err.println("Can't upload File! Reply from Server: " + ftpClient.getReplyString());
} else {
    System.out.println("Upload successful");
}

PS: the FTPClient rarely shows an error or warning message, therefore it's better to add a PrintCommandListener to debug.

ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
  • @Robert you have in the example for `ftpUser`the value `domain\username` is there also a backslash in the real username? If so you have to escape the backslash. –  Oct 13 '17 at 09:44
  • you are correct.. I logged in successfully after changing \ to / in username. but still can't have file uploaded successfully. – Robert Oct 13 '17 at 09:45
  • thansk a lot for your relpy, I have logged in but still can't upload the file... I have updated the thread, could you please provide some suggestion ? – Robert Oct 13 '17 at 09:51
  • @Robert it seems like the filename `/wwwroot/preview/history.txt` is incorrect or you don't have write permission –  Oct 13 '17 at 09:53
  • @ devpuh, I think the credentails have the write the permission, as the same credential is used in FileZilla which succeeded... However, I am also wondering if the file name "/wwwroot/preview/history.txt" is incorrect, basically, after root path after login in filezilla is just "/", then navigate into "/wwwroot/preview" then upload the file. Therefore I set the filename as "/wwwroot/preview/history.txt". Do you have any idea how to change it if it is the issue? – Robert Oct 13 '17 at 10:02
  • @Robert you can change the working directory on the ftp-server with `ftpClient.changeWorkingDirectory("wwwroot/preview");` and than upload the file. –  Oct 13 '17 at 10:12
  • sorry for the late update, as I have no Internet access for last 2 days. It works after adding ftpClient.changeWorkingDirectory("wwwroot/preview"); thanks a lot for the patient response for my changing questions. – Robert Oct 16 '17 at 03:37
  • To make it have file real uploaded to FTP server, two more lines were added to code: ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.execPBSZ(0); // Set protection buffer size ftpClient.execPROT("P"); // Set data channel protection to private ftpClient.enterLocalPassiveMode(); – Robert Oct 16 '17 at 07:07