0
点赞
收藏
分享

微信扫一扫

ftp上传错误org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication

修炼之士 2022-01-08 阅读 72

报错信息

ftp上传文件报org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication错误
在这里插入图片描述
项目中由于ftp做了迁移,代码使用的ftpclient登录成功,但是上传文件就报这个错误。

代码

public boolean uploadFile(String ip, int port, String username,  
			   String password, String serverpath, String file) {
		 // 初始表示上传失败  
		 boolean success = false;  
		 // 创建FTPClient对象  
		 FTPClient ftp = new FTPClient();  
		 ftp.setControlEncoding("UTF-8");
		 ftp.setConnectTimeout(20000);
		 ftp.setDataTimeout(600000);
		 ftp.enterLocalPassiveMode();
		 ftp.setActivePortRange(4000, 4100);

		 try {
			 int reply=0;  
			 // 连接FTP服务器  
			 // 如果采用默认端口,可以使用ftp.connect(ip)的方式直接连接FTP服务器  
			 ftp.connect(ip, port);  
			 //ftp.connect("192.168.20.221", 21);  
			 // 登录ftp

             ftp.login(username, password);
			 // 看返回的值是不是reply>=200&&reply<300 如果是,表示登陆成功

             reply = ftp.getReplyCode();
             logger.info("连接ftp服务器响应码,reply={}",reply);

             // 以2开头的返回值就会为真
			 if (!FTPReply.isPositiveCompletion(reply)) {
                 ftp.disconnect();
				 return success;  
			 }
			   
			 ftp.setActivePortRange(40000, 41000);

			 logger.info("ftp连接成功。。。file = {}, serverpath = {}", file, serverpath);
			 checkPathExist(ftp,iso8859ToGbk(serverpath));
     
			 //输入流  
			 InputStream input=null;
			 try {  
				 file=gbkToIso8859(file);  
				 input = new FileInputStream(iso8859ToGbk(file));  
			 } catch (Exception e) {
				 LoggerFactory.getLogger(this.getClass()).error("读取上传文件出错",e);
			 }  
			 // 将上传文件存储到指定目录  
			 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("上传前ftp路径,ftpPath = {}",ftpPath);

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

             logger.info("上传文件后,上传结果flag = {}", flag);

             // 关闭输入流
			 input.close();
			 
			 if(flag){
				 ftp.rename(iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(tmpFileName),
						 iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(fileName));
				 success = true;
			 }

			 // 退出ftp  
			 ftp.logout();  
		 } catch (IOException e) {  
			 success = false;
			 LoggerFactory.getLogger(this.getClass()).error("上传数据到ftp出错",e);
		 } finally {  
			 if (ftp.isConnected()) {  
				 try {  
					 ftp.disconnect();  
				 } catch (IOException ioe) {  
					 LoggerFactory.getLogger(this.getClass()).info(ioe.toString());
				 }  
			 }  
		 }  
		 return success;  
	 } 

ftp主被动模式介绍

主动模式:FTP客户端向服务器的FTP控制端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路;当需要传送数据时,客户端在命令链路上用PORT的命令告诉服务器我开放了某端口,你过来连接我。于是服务器从20端口向客户端的该端口发送连接请求,建立一条数据链路来传送数据。在数据链路建立过程中是服务器主动请求,所以称为主动模式。

被动模式:FTP客户端向服务器的FTP控制端口(默认21)发送连接请求,服务器接受连接,建立一条命令链路;当需要传送数据时,服务器在命令链路上用PASV命令告诉客户端,我打开了某端口,你过来连我。于是客户端向服务器的该端口发送连接请求,建立一条数据链路来传送数据。在数据链路建立的过程中是服务器被动等待客户机的请求,所以称被动模式。

原因分析

看我们上面的代码,就知道,在ftp登录成功后,执行了ftp.setActivePortRange(40000, 41000);,这个表示使用主动模式传输数据,主动模式需要ftp服务器连我们的端口,结果,由于网络问题,ftp服务器无法连接客户端的端口,所以就报了这个错误。

解决方案

对于这个问题,应该有两种解决方案:一、开通网络,是ftp服务器能够连接客户端40000~41000的端口;二、就是改成被动模式。
在这里我就采取了第二种方法:在ftp客户端登录成功后(在登录之前执行是无效的),执行ftp.enterLocalPassiveMode();就可以了,最终代码如下:

public boolean uploadFile(String ip, int port, String username,  
			   String password, String serverpath, String file) {
		 // 初始表示上传失败  
		 boolean success = false;  
		 // 创建FTPClient对象  
		 FTPClient ftp = new FTPClient();  
		 ftp.setControlEncoding("UTF-8");
		 ftp.setConnectTimeout(20000);
		 ftp.setDataTimeout(600000);
		 ftp.enterLocalPassiveMode();
		 ftp.setActivePortRange(4000, 4100);

		 try {
			 int reply=0;  
			 // 连接FTP服务器  
			 // 如果采用默认端口,可以使用ftp.connect(ip)的方式直接连接FTP服务器  
			 ftp.connect(ip, port);  
			 //ftp.connect("192.168.20.221", 21);  
			 // 登录ftp

             ftp.login(username, password);
			 // 看返回的值是不是reply>=200&&reply<300 如果是,表示登陆成功

             reply = ftp.getReplyCode();
             logger.info("连接ftp服务器响应码,reply={}",reply);

             // 以2开头的返回值就会为真
			 if (!FTPReply.isPositiveCompletion(reply)) {
                 ftp.disconnect();
				 return success;  
			 }
			   
			 ftp.enterLocalPassiveMode();// 这是改为被动模式

			 logger.info("ftp连接成功。。。file = {}, serverpath = {}", file, serverpath);
			 checkPathExist(ftp,iso8859ToGbk(serverpath));
     
			 //输入流  
			 InputStream input=null;
			 try {  
				 file=gbkToIso8859(file);  
				 input = new FileInputStream(iso8859ToGbk(file));  
			 } catch (Exception e) {
				 LoggerFactory.getLogger(this.getClass()).error("读取上传文件出错",e);
			 }  
			 // 将上传文件存储到指定目录  
			 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("上传前ftp路径,ftpPath = {}",ftpPath);

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

             logger.info("上传文件后,上传结果flag = {}", flag);

             // 关闭输入流
			 input.close();
			 
			 if(flag){
				 ftp.rename(iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(tmpFileName),
						 iso8859ToGbk(serverpath)+"/"+iso8859ToGbk(fileName));
				 success = true;
			 }

			 // 退出ftp  
			 ftp.logout();  
		 } catch (IOException e) {  
			 success = false;
			 LoggerFactory.getLogger(this.getClass()).error("上传数据到ftp出错",e);
		 } finally {  
			 if (ftp.isConnected()) {  
				 try {  
					 ftp.disconnect();  
				 } catch (IOException ioe) {  
					 LoggerFactory.getLogger(this.getClass()).info(ioe.toString());
				 }  
			 }  
		 }  
		 return success;  
	 } 

期望对大家有所帮助。

举报

相关推荐

0 条评论