0

i need help i'm trying to create the connection with the FTP'Server where i upload my file.
i'm using below dependency with java jdk1.8.0_45. when i run my code it's make connection and also login but when i try to upload file it's throw Exception and upload empty file

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:980)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:619)
at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:633)
at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:624)
at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:1976)
at org.quorum.appnexusutility.transfer.TransferManager.uploadFile(TransferManager.java:176)
at org.quorum.appnexusutility.transfer.TransferManager.pushFile(TransferManager.java:220)
at org.quorum.appnexusutility.transfer.TransferManager.main(TransferManager.java:233)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:961)
... 10 more

Dependency

<dependency>
        <groupId>commons-net</groupId>
        <artifactId>commons-net</artifactId>
        <version>3.3</version>
</dependency>

Below code i change the host may not work for you

package org.quorum.appnexusutility.transfer;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Socket;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.Locale;


@Component
@Scope("prototype")
public class TransferManager {

    public Logger logger = LogManager.getLogger(TransferManager.class);

    // SSL/TLS
    private final Integer TENSECONDS  = 10*1000; // 10 second
    private final String protocol = "TLS";//"TLS";
    private Boolean isLogin = false;
    private Boolean isUpload = false;
    private String directoryPath;
    private String host;
    private Integer port;
    private String user;
    private String password;
    private FTPSClient ftpsClient;

    public TransferManager() { }

    public String getHost() { return host; }
    public TransferManager setHost(String host) {
        this.host = host;
        return this;
    }

    public Integer getPort() { return port; }
    public TransferManager setPort(Integer port) {
        this.port = port;
        return this;
    }

    public String getUser() { return user; }
    public TransferManager setUser(String user) {
        this.user = user;
        return this;
    }

    public String getPassword() { return password; }
    public TransferManager setPassword(String password) {
        this.password = password;
        return this;
    }

    public String getDirectoryPath() { return directoryPath; }
    public void setDirectoryPath(String directoryPath) {
        this.directoryPath = directoryPath;
    }

    public void open() throws IOException {
        //System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
        //this.ftpsClient = new SSLSessionReuseFTPSClient();
        //ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
        if(this.port > 100) {
            this.ftpsClient = new FTPSClient(this.protocol, true);
        } else {
            this.ftpsClient = new FTPSClient(false);
        }
        this.ftpsClient.setControlKeepAliveTimeout(TENSECONDS);
        this.showServerReply(this.ftpsClient);
        logger.info("FTP :- Connection try :- IP :- (" + this.host + ") , Port :- " + this.port + " Start");
        this.ftpsClient.connect(this.host, this.port);
        this.ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
        logger.info("FTP :- Connection try :- IP :- (" + this.host + ") , Port :- " + this.port + " Done");
        int reply = this.ftpsClient.getReplyCode();
        logger.info("FTP :- Connection Code :- " + reply);
        if(!FTPReply.isPositiveCompletion(reply)) {
            this.ftpsClient.disconnect();
            throw new IOException("Exception in connecting to FTP Server");
        }
        this.isLogin = this.ftpsClient.login(user, password);
        this.showServerReply(this.ftpsClient);
        logger.info("FTP :- Login Status :- " + this.isLogin);
    }

    private Boolean makeDirectory() throws IOException {
        Boolean isDirectoryCreate = false;
        if(this.isLogin && this.directoryPath != null) {
            isDirectoryCreate = this.ftpsClient.makeDirectory(this.directoryPath);
            this.showServerReply(this.ftpsClient);
            if (isDirectoryCreate) {
                logger.info("Successfully created directory: " + this.directoryPath);
            } else {
                logger.info("Failed to create directory. See server's reply.");
            }
        }
        return isDirectoryCreate;
    }

    //  if returns 250, folder exists  and if returned 550 folder does not exist***
    private Boolean isDirectoryExist() throws IOException {
        if(this.ftpsClient.cwd(this.directoryPath) == 550) {
            logger.info("Directory Not Exist");
            return false;
        } else {
            logger.info("Directory Exist");
            return true;
        }
    }

    // upload process
    public Boolean uploadFile(File file) throws Exception {
        if(this.isLogin && this.directoryPath != null) {
            if(!this.isDirectoryExist()) {
                // call when not exist
                this.makeDirectory();
            }
            this.ftpsClient.enterLocalPassiveMode();
            this.ftpsClient.execPBSZ(0);
            this.ftpsClient.execPROT("P");
            this.ftpsClient.setFileType(FTP.BINARY_FILE_TYPE);
            // only the text file can be upload
            //this.ftpsClient.setFileType(FTP.TELNET_TEXT_FORMAT);
            this.ftpsClient.changeWorkingDirectory(this.getDirectoryPath());
            logger.info("Current Directory " + this.ftpsClient.printWorkingDirectory());
            FileInputStream fileInputStream = new FileInputStream(file);
            String filePath = RandomStringUtils.randomAlphanumeric(8)+".txt";
            logger.info("Final Path :- " + filePath);
            //this.isUpload =
                    this.ftpsClient.storeFile(filePath, fileInputStream);
            if(this.isUpload) {
                logger.info("The file is uploaded successfully.");
            }
            // close the stream which use to store the file
            fileInputStream.close();
        }
        return this.isUpload;
    }

    // connection close for client
    public void close() throws IOException {
        if (this.ftpsClient.isConnected()) {
            this.ftpsClient.logout();
            this.ftpsClient.disconnect();
        }
    }

    public String getDirectoryPathRandom() {
        Date date = new Date();
        LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        int year  = localDate.getYear();
        int month = localDate.getMonthValue();
        int day   = localDate.getDayOfMonth();
        int hours = date.getHours();
        logger.info("Year :- (" + year + ") Month :- (" + month + ") Day :- (" + day + ") Hours :- (" + hours + ")");
        return year + "/"+ month + "/" + day + "/" + hours;
    }

    private void showServerReply(FTPSClient ftpsClient) {
        String[] replies = ftpsClient.getReplyStrings();
        if (replies != null && replies.length > 0) {
            for (String aReply : replies) {
                logger.info("SERVER: " + aReply);
            }
        }
    }
    // this method use to push the file from 1 server to other server
    public static void pushFile(String host, int port, String user, String password, File file) throws Exception {
        TransferManager transferManager = new TransferManager().setHost(host).setPort(port).setUser(user).setPassword(password);
        // we push the fiel on the base of yyyy/mm/dd/hr
        // first check if the dir exist then no need to create the directory
        transferManager.setDirectoryPath(transferManager.getDirectoryPathRandom());
        transferManager.open(); // open connection
        transferManager.uploadFile(file); // file
        transferManager.close(); // close connection
    }

    //======================FTP=========================
    //FTP URL: ftp.dlptest.com or ftp://ftp.dlptest.com/
    //FTP User: [email protected]
    //Password: bbCKucPzfr4b9YXUY7tvsNKyh
    public static void main(String args[]) throws Exception {
        pushFile("ftps.xyzserver.com", 990, "macak", "Go447641", new File("C:\\Users\\Nabeel.Ahmed\\Desktop\\Study-Pending\\Detail Document.txt"));
    }
}

enter image description here

3 Answers 3

1

It seems to be the problem with SSL/TLS protocol version issue. Go through the following post SSL peer shut down incorrectly in Java You should get the answer.

Sign up to request clarification or add additional context in comments.

Comments

1

Can you try to replace the following line

private final String protocol = "TLS";//"TLS";

with

private final String protocol = "TLSv1.1";

2 Comments

thanks for replay but it's not work same error i'm getting in console
0

All after lot of search and finally found the solution by reuse the method of prepareDataSocket here the code.

import org.apache.commons.net.ftp.FTPSClient;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Locale;


public class ModifiedFTPSClient extends FTPSClient {

    public ModifiedFTPSClient() {
        super("TLS", false);
    }

    public ModifiedFTPSClient(boolean isImplicit) {
        super("TLS", isImplicit);
    }

    @Override
    protected void _prepareDataSocket_(final Socket socket) throws IOException {
        if (socket instanceof SSLSocket) {
            final SSLSession session = ((SSLSocket) _socket_).getSession();
            if (session.isValid()) {
                final SSLSessionContext context = session.getSessionContext();
            try {
                final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
                sessionHostPortCache.setAccessible(true);
                final Object cache = sessionHostPortCache.get(context);
                final Method method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                method.setAccessible(true);
                method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostName(), String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session);
                method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostAddress(), String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session);
            } catch (NoSuchFieldException e) {
                throw new IOException(e);
            } catch (Exception e) {
                throw new IOException(e);
            }
        } else {
            throw new IOException("Invalid SSL Session");
        }
    }
}

Above Question Class TransferManager replace the class like this

private String user;
private String password;
private ModifiedFTPSClient ftpsClient;

Above Question Class TransferManager replace the value in open() method

if(this.port > 100) {
    this.ftpsClient  = new ModifiedFTPSClient(true); // fro ftps
} else {
    this.ftpsClient = new ModifiedFTPSClient(); // fro ftp
}

1 Comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.