FTP upload error org apache. commons. net. ftp. FTPConnectionClosedException: Connection closed without indication

Posted by etones on Sat, 08 Jan 2022 10:39:11 +0100

Error message

FTP upload file report org apache. commons. net. ftp. Ftpconnectionclosedexception: connection closed without indication error

In the project, due to ftp migration, the ftpclient used by the code logs in successfully, but this error is reported when uploading the file.

code

public boolean uploadFile(String ip, int port, String username,  
			   String password, String serverpath, String file) {
		 // Initial indicates upload failed  
		 boolean success = false;  
		 // Create FTPClient object  
		 FTPClient ftp = new FTPClient();  
		 ftp.setControlEncoding("UTF-8");
		 ftp.setConnectTimeout(20000);
		 ftp.setDataTimeout(600000);
		 ftp.enterLocalPassiveMode();
		 ftp.setActivePortRange(4000, 4100);

		 try {
			 int reply=0;  
			 // Connect to FTP server  
			 // If you use the default port, you can use FTP Connect (IP) directly to the FTP server  
			 ftp.connect(ip, port);  
			 //ftp.connect("192.168.20.221", 21);  
			 // Login ftp

             ftp.login(username, password);
			 // Check whether the returned value is reply > = 200 & & reply < 300. If yes, it indicates that the login is successful

             reply = ftp.getReplyCode();
             logger.info("connect ftp Server response code, reply={}",reply);

             // The return value starting with 2 will be true
			 if (!FTPReply.isPositiveCompletion(reply)) {
                 ftp.disconnect();
				 return success;  
			 }
			   
			 ftp.setActivePortRange(40000, 41000);

			 logger.info("ftp Connection succeeded... file = {}, serverpath = {}", file, serverpath);
			 checkPathExist(ftp,iso8859ToGbk(serverpath));
     
			 //Input stream  
			 InputStream input=null;
			 try {  
				 file=gbkToIso8859(file);  
				 input = new FileInputStream(iso8859ToGbk(file));  
			 } catch (Exception e) {
				 LoggerFactory.getLogger(this.getClass()).error("Error reading uploaded file",e);
			 }  
			 // Store the uploaded file in the specified directory  
			 file=iso8859ToGbk(file);
			 
			 String fileName =  getFilename(file);//8859
			 
			 int index = fileName.lastIndexOf(".");
			 String tmpFileName = fileName.substring(0,index)+".tmp";
			 
			 ftp.deleteFile(iso8859ToGbk(fileName));
			 
			 ftp.setFileType(FTPClient.BINARY_FILE_TYPE);

			 String ftpPath = iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(tmpFileName);

			 logger.info("Before uploading ftp route, ftpPath = {}",ftpPath);

			 boolean flag = ftp.storeFile(ftpPath, input);

             logger.info("After uploading the file, upload the results flag = {}", flag);

             // Close input stream
			 input.close();
			 
			 if(flag){
				 ftp.rename(iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(tmpFileName),
						 iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(fileName));
				 success = true;
			 }

			 // Exit ftp  
			 ftp.logout();  
		 } catch (IOException e) {  
			 success = false;
			 LoggerFactory.getLogger(this.getClass()).error("Upload data to ftp error",e);
		 } finally {  
			 if (ftp.isConnected()) {  
				 try {  
					 ftp.disconnect();  
				 } catch (IOException ioe) {  
					 LoggerFactory.getLogger(this.getClass()).info(ioe.toString());
				 }  
			 }  
		 }  
		 return success;  
	 } 

Introduction to ftp active and passive mode

Active mode: the FTP client sends a connection request to the FTP control PORT (21 by default) of the server, and the server accepts the connection and establishes a command link; When it is necessary to transmit data, the client uses the PORT command on the command link to tell the server that I have opened a PORT, and you come to connect me. Therefore, the server sends a connection request from PORT 20 to the PORT of the client and establishes a data link to transmit data. In the process of data link establishment, the server actively requests, so it is called active mode.

Passive mode: the FTP client sends a connection request to the FTP control port (default 21) of the server, and the server accepts the connection and establishes a command link; When data needs to be transmitted, the server uses PASV command on the command link to tell the client that I have opened a port and you come to connect me. So the client sends a connection request to the port of the server and establishes a data link to transmit data. In the process of data link establishment, the server passively waits for the request of the client, so it is called passive mode.

Cause analysis

From the code above, we can see that after the ftp login is successful, ftp is executed setActivePortRange(40000, 41000);, This means that the active mode is used to transmit data. The active mode requires the ftp server to connect to our port. As a result, the ftp server cannot connect to the client port due to network problems, so this error is reported.

Solution

For this problem, there should be two solutions: first, open the network, which is the port where the ftp server can connect the client 40000 ~ 41000; 2, Is to change to passive mode.
Here I take the second method: after the ftp client logs in successfully (the execution before login is invalid), execute ftp enterLocalPassiveMode(); The final code is as follows:

public boolean uploadFile(String ip, int port, String username,  
			   String password, String serverpath, String file) {
		 // Initial indicates upload failed  
		 boolean success = false;  
		 // Create FTPClient object  
		 FTPClient ftp = new FTPClient();  
		 ftp.setControlEncoding("UTF-8");
		 ftp.setConnectTimeout(20000);
		 ftp.setDataTimeout(600000);
		 ftp.enterLocalPassiveMode();
		 ftp.setActivePortRange(4000, 4100);

		 try {
			 int reply=0;  
			 // Connect to FTP server  
			 // If you use the default port, you can use FTP Connect (IP) directly to the FTP server  
			 ftp.connect(ip, port);  
			 //ftp.connect("192.168.20.221", 21);  
			 // Login ftp

             ftp.login(username, password);
			 // Check whether the returned value is reply > = 200 & & reply < 300. If yes, it indicates that the login is successful

             reply = ftp.getReplyCode();
             logger.info("connect ftp Server response code, reply={}",reply);

             // The return value starting with 2 will be true
			 if (!FTPReply.isPositiveCompletion(reply)) {
                 ftp.disconnect();
				 return success;  
			 }
			   
			 ftp.enterLocalPassiveMode();// This is changed to passive mode

			 logger.info("ftp Connection succeeded... file = {}, serverpath = {}", file, serverpath);
			 checkPathExist(ftp,iso8859ToGbk(serverpath));
     
			 //Input stream  
			 InputStream input=null;
			 try {  
				 file=gbkToIso8859(file);  
				 input = new FileInputStream(iso8859ToGbk(file));  
			 } catch (Exception e) {
				 LoggerFactory.getLogger(this.getClass()).error("Error reading uploaded file",e);
			 }  
			 // Store the uploaded file in the specified directory  
			 file=iso8859ToGbk(file);
			 
			 String fileName =  getFilename(file);//8859
			 
			 int index = fileName.lastIndexOf(".");
			 String tmpFileName = fileName.substring(0,index)+".tmp";
			 
			 ftp.deleteFile(iso8859ToGbk(fileName));
			 
			 ftp.setFileType(FTPClient.BINARY_FILE_TYPE);

			 String ftpPath = iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(tmpFileName);

			 logger.info("Before uploading ftp route, ftpPath = {}",ftpPath);

			 boolean flag = ftp.storeFile(ftpPath, input);

             logger.info("After uploading the file, upload the results flag = {}", flag);

             // Close input stream
			 input.close();
			 
			 if(flag){
				 ftp.rename(iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(tmpFileName),
						 iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(fileName));
				 success = true;
			 }

			 // Exit ftp  
			 ftp.logout();  
		 } catch (IOException e) {  
			 success = false;
			 LoggerFactory.getLogger(this.getClass()).error("Upload data to ftp error",e);
		 } finally {  
			 if (ftp.isConnected()) {  
				 try {  
					 ftp.disconnect();  
				 } catch (IOException ioe) {  
					 LoggerFactory.getLogger(this.getClass()).info(ioe.toString());
				 }  
			 }  
		 }  
		 return success;  
	 } 

I hope it will be helpful to you.

Topics: Apache .NET server