首先我们需要查看是否已经安装vsftpd,输入命令 :vsftpd  -v。如果出现以下信息,那么就说明已经安装vsftpd

如果没有安装,那么输入命令   : yum  install vsftpd -y 进行安装,出现complete说明安装成功。

现在去我们先创建一下用户 , 命令:useradd  -d /home/ftpuser ftpuser   -d是为用户ftpuser 指定主目录,默认是/home下对应用户名的一个文件夹。

接着设置用户密码 : passwd ftpuser .输入两次以后显示successfully就说明设置好了。

接着我们需要查看一下本机外网访问权限,这个一定要开。不然会执行失败:输入 getsebool -a |grep ftp 

我们发现这两个状态是关着的,我们要把他开起来,同事也要关闭防火墙

这样子就开起来了。接下去我们需要配置一下vsftpd 的配置文件 进入配置文件目录

其实默认的配置文件就可以满足基本的功能,如果我们需要关闭匿名操作,那么我们把anonymous_enable设置为NO就可以了。

vsftpd的默认端口为21,在不太了解vsftpd的情况下,切记不要去改他。一定不要去改,一定不要!!

接下去就是JAVA代码了

上传功能的代码:上传过程可能遇到进入文件夹失败,这里推荐大家用绝对路径!!!

/** 
	 * 初始化ftp服务器 
	 *  
	 * @throws IOException 
	 * @throws SocketException 
	 */ 
	public void initFtpClient() throws SocketException, IOException { 
		ftpClient = new FTPClient(); 
		ftpClient.setControlEncoding("utf-8"); 
		LOGGER.info("connecting...ftp服务器:" + this.hostname + ":" + this.port); 
		ftpClient.connect(hostname, port); // 连接ftp服务器 
		ftpClient.login(username, password); // 登录ftp服务器 
		int replyCode = ftpClient.getReplyCode(); // 是否成功登录服务器 
		if (!FTPReply.isPositiveCompletion(replyCode)) { 
			LOGGER.info("connect failed...ftp服务器:" + this.hostname + ":" + this.port); 
		} 
		LOGGER.info("connect successfu...ftp服务器:" + this.hostname + ":" + this.port); 
 
	} 
 
	/** 
	 * 上传文件 
	 *  
	 * @param pathname 
	 *            ftp服务保存地址 
	 * @param fileName 
	 *            上传到ftp的文件名 
	 * @param inputStream 
	 *            输入文件流 
	 * @return 
	 * @throws IOException 
	 */ 
	public boolean uploadFile(String pathname, String fileName, InputStream inputStream) throws IOException { 
		boolean flag = false; 
		initFtpClient(); 
		try { 
			LOGGER.info("开始上传文件"); 
			ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE); 
//			CreateDirecroty(pathname); 
			 
			boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(pathname); 
			if(changeWorkingDirectory) { 
				LOGGER.info("进入文件"+pathname+"夹成功."); 
			}else { 
				LOGGER.info("进入文件"+pathname+"夹失败.开始创建文件夹"); 
				boolean makeDirectory = ftpClient.makeDirectory(pathname); 
				if(makeDirectory) { 
					LOGGER.info("创建文件夹"+pathname+"成功"); 
					boolean changeWorkingDirectory2 = ftpClient.changeWorkingDirectory(pathname); 
					if(changeWorkingDirectory2) { 
						LOGGER.info("进入文件"+pathname+"夹成功."); 
					} 
				}else { 
					LOGGER.info("创建文件夹"+pathname+"失败"); 
				} 
			} 
			ftpClient.storeFile(fileName, inputStream); 
			inputStream.close(); 
			ftpClient.logout(); 
			flag = true; 
			if (flag) { 
 
				LOGGER.info("上传文件成功"); 
			} 
		} finally { 
			if (ftpClient.isConnected()) { 
				try { 
					ftpClient.disconnect(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
			if (null != inputStream) { 
				try { 
					inputStream.close(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
		} 
		return true; 
	}  

接下去就是上传的功能了,我这里约到一个很奇怪的现象,就是通过ftpclientd获取文件列表的时候有随机性,有时候可以获取到,有时候却是空的,就是ftpclient.listFiles()方法。网上的说法是添加方法ftpClient.enterLocalPassiveMode();,可是我这里添加了这个方法就连接超时。也有人说是防火墙一系列问题。那么首先是vsftpd的主动被动问题。vsftpd的配置文件是默认启用的主动模式。要改成被动模式的话,这边需要修改配置文件,我用的主动模式 。输入命令 vim /etc/vsftpd/vsftpd.conf  ,修改之前记得先备份一份配置文件。 然后:

这么改,启动被动模式,关闭主动模式,随后重启vsftpd.我试过仅仅这样子改是不行的,我们需要去查看一下SELinux防火墙的状态:

我这里是宽容模式。SELinux有3种状态,Permissive (宽容模式), Disabled , Enforcing(强制)在配置文件/etc/selinux/config中定义,要永久关闭SELinux防火墙需要将SELINUX=Permissive改为SELINUX=disabled,这里一定要重启系统。如果是启用就将disabled改成其他的,也需要重启。我这边是强制改成宽容,只需要输入命令setenforce 1 就可以了,不需要重启计算机。修改完这里,我们还要设置防火墙FireWall防火墙。

firewall-cmd --permanent --zone=public --add-port=10090-10100/tcp

firewall-cmd --reload

显示success就可以了。。。

接下去要增加两个模块。。不然被动模式会连接失败,编辑  /etc/sysconfig/iptables-config  文件

IPTABLES_MODULES="ip_conntrack_ftp"
IPTABLES_MODULES="ip_nat_ftp"

添加完这两行 保存设置  firewall-cmd --reload 。 

这里的配置有乱,我后来把防火墙也禁用了。SELinux也禁用了。

可能根本不需要这些配置,大家在实操的时候可以先把防火墙跟SELinux都先禁用。看看实际运行情况再考虑要不要做这些配置,我这里是遇到获取不到文件。所以百度了很多文章,做了很多配置,毕竟不熟悉。

接下去就是下载 跟 删除的代码了:

/** 
	 * * 下载文件 * 
	 *  
	 * @param pathname 
	 *            FTP服务器文件目录 * 
	 * @param filename 
	 *            文件名称 * 
	 * @param localpath 
	 *            下载后的文件路径 * 
	 * @return 
	 * @throws IOException  
	 */ 
	public byte[] downloadFile(String pathname, String filename, String localpath) throws IOException { 
		boolean flag = false; 
		OutputStream os = null; 
		byte[] buffer = null; 
		initFtpClient(); 
		try { 
			LOGGER.info("开始下载文件"); 
//			ftpClient.enterLocalPassiveMode(); 
//			FTPClientConfig conf = new FTPClientConfig( FTPClientConfig.SYST_UNIX); 
//			ftpClient.configure(conf); 
			// 切换FTP目录 
			boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(pathname); 
			if(!changeWorkingDirectory) { 
				throw new FTPTransferException(FTPError.changeDirectoryError) ; 
			}else { 
				LOGGER.info("进入目"+pathname+"录成功。"); 
			} 
 
			FTPFile[] ftpFiles = ftpClient.listFiles(pathname, new FTPFileFilter() { 
 
				@Override 
				public boolean accept(FTPFile file) { 
					if (file.getName().equals(filename)) { 
						return true; 
					} 
					return false; 
				} 
			}); 
			for (int i=0;i<ftpFiles.length && flag ==false;i++) { 
				FTPFile file = ftpFiles[i]; 
				if (filename.equalsIgnoreCase(file.getName())) { 
					flag = true; 
					setFileSize(file.getSize()); 
					InputStream fis = ftpClient.retrieveFileStream(file.getName()); 
					buffer = new byte[fis.available()]; 
					int read = fis.read(buffer); 
					fis.close(); 
					LOGGER.info("下载文件成功"); 
				} 
			} 
			ftpClient.logout(); 
 
		}  finally { 
			if (ftpClient.isConnected()) { 
				try { 
					ftpClient.disconnect(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
			if (null != os) { 
				try { 
					os.close(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
		} 
		return buffer; 
	} 
 
	/** 
	 * * 删除文件 * 
	 *  
	 * @param pathname 
	 *            FTP服务器保存目录 * 
	 * @param filename 
	 *            要删除的文件名称 * 
	 * @return 
	 * @throws IOException  
	 */ 
	public boolean deleteFile(String pathname, String filename) throws IOException { 
		boolean flag = false; 
		try { 
			LOGGER.info("开始删除文件"); 
			initFtpClient(); 
			// 切换FTP目录 
			boolean changeWorkingDirectory = ftpClient.changeWorkingDirectory(pathname); 
			if(!changeWorkingDirectory) { 
				throw new FTPTransferException(FTPError.changeDirectoryError) ; 
			}else { 
				LOGGER.info("进入目"+pathname+"录成功。"); 
			} 
 
			FTPFile[] ftpFiles = ftpClient.listFiles(pathname, new FTPFileFilter() { 
 
				@Override 
				public boolean accept(FTPFile file) { 
					if (file.getName().equals(filename)) { 
						return true; 
					} 
					return false; 
				} 
			}); 
			if (ftpFiles == null || ftpFiles.length == 0) { 
				LOGGER.info("删除文件失败,文件不存在"); 
				throw new FTPTransferException(FTPError.fileNotFound) ; 
			} else { 
 
				ftpClient.dele(filename); 
				ftpClient.logout(); 
				flag = true; 
			} 
			if(flag) { 
				 
				LOGGER.info("删除文件成功"); 
			} 
		} finally { 
			if (ftpClient.isConnected()) { 
				try { 
					ftpClient.disconnect(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
		} 
		return flag; 
	} 

这样下来基本功能就差不多都可以实现了。。经过验证,获取不到列表的我,应该不是主动被动的关系,到最后我还是改成了主动,最终确定是SELinux的锅,一定把他的强制模式关闭。在调试前,一定要看看SELinux的状态,跟防火墙的状态。都给他关了 排除干扰,一般来说程序就没什么问题了


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!