java实现FTP和 SFTP连接远程服务器下载文件

java实现FTP和 SFTP连接远程服务器下载文件


前言

为什魔写这片文章呢,因为关于ftp和sftp的文章介绍的太少啦 。


提示:以下是本篇文章正文内容,下面案例可供参考

一、FTP是什么?如何实现。

来自百度百科 :文件传输协议(File Transfer Protocol,FTP)是用于在网络上进行文件传输的一套标准协议,它工作在 OSI 模型的第七层, TCP 模型的第四层, 即应用层, 使用 TCP 传输而不是 UDP, 客户在和服务器建立连接前要经过一个“三次握手”的过程, 保证客户与服务器之间的连接是可靠的, 而且是面向连接, 为数据传输提供可靠保证。
FTP允许用户以文件操作的方式(如文件的增、删、改、查、传送等)与另一主机相互通信。然而, 用户并不真正登录到自己想要存取的计算机上面而成为完全用户, 可用FTP程序访问远程资源, 实现用户往返传输文件、目录管理以及访问电子邮件等等, 即使双方计算机可能配有不同的操作系统和文件存储方式。

1.实现代码


public class FtpTools {
    
    
	public static Logger logger = SnowLog.getLogger(FtpTools.class);
	private static String ftpHost; 										// IP
	private static int ftpPort; 										// port
	private static String ftpUserName; 									// 用户
	private static String ftpPassword; 									// 密码
	private static FTPClient ftpClient; 								// IP
	/**
	 * 初始化ftp信息
	 * @param type
	 * @throws Exception
	 */
	public void init(String type) throws Exception {
    
    
		logger.info("***********************初始化FTP信息***********************");
		String hostMagicId = null;
		String userNameMagicId = null;
		String passWordMagicId = null;
		String cbsPortMagicId=null;
		if(InterConstants.FTP_CBS_01.equals(type)){
    
    
			hostMagicId = "CBS_HOST";
			userNameMagicId = "CBS_USERNAME";
			passWordMagicId = "CBS_PASSWORD";
			cbsPortMagicId="CBS_PORT";
		}else{
    
    
			SnowExceptionUtil.throwErrorException("ftp类型非法,初始化ftp信息失败");
		}
		TblSysParam selectHost = DBDaos.newInstance().select(TblSysParam.class, "FTP", hostMagicId);
		if (selectHost == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP地址!");
		}
		ftpHost = selectHost.getParamValueTx();
		TblSysParam selectPort = DBDaos.newInstance().select(TblSysParam.class, "FTP", cbsPortMagicId);
		if (selectPort == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP端口!");
		}
		ftpPort = Integer.parseInt(selectPort.getParamValueTx());
		TblSysParam selectUsername = DBDaos.newInstance().select(TblSysParam.class, "FTP", userNameMagicId);
		if (selectUsername == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP用户名!");
		}
		ftpUserName = selectUsername.getParamValueTx();
		TblSysParam selectPassword = DBDaos.newInstance().select(TblSysParam.class, "FTP", passWordMagicId);
		if (selectPassword == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP密码!");
		}
		ftpPassword = selectPassword.getParamValueTx();

	}

	/**
	 * 连接ftp服务
	 * @throws Exception
	 */
	public  void connectClient() throws Exception {
    
    
		logger.info("***********************登录FTP***********************");
		ftpClient = new FTPClient();
		try {
    
    
			ftpClient = new FTPClient();
			ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
			ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
			//设置编码
			ftpClient.setControlEncoding("GBK");
			ftpClient.setBufferSize(8096);
			if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
    
    
				logger.info("未连接到FTP,用户名或密码错误。");
				ftpClient.disconnect();
			} else {
    
    
				logger.info("FTP连接成功。");
			}
		} catch (SocketException e) {
    
    
			logger.error("FTP的IP地址可能错误,请正确配置。message={}",e);
			SnowExceptionUtil.throwErrorException("FTP服务器连接失败");
		} catch (IOException e) {
    
    
			logger.error("FTP的端口错误,请正确配置。message={}",e);
			SnowExceptionUtil.throwErrorException("FTP服务器连接失败");
		}catch (Exception e) {
    
    
			logger.error("FTP连接失败。message={}",e);
			SnowExceptionUtil.throwErrorException("FTP服务器连接失败");
		}
	}

	/**
	 *  检验指定路径的文件是否存在ftp服务器中
	 * @param filePath--指定绝对路径的文件
	 * @return
	 */
	public  boolean isFTPFileExist(String filePath){
    
    
		// 判断文件是否存在
		Boolean isexist = false;
		try {
    
    
			// 提取绝对地址的目录以及文件名
			filePath = filePath.replace("ftp://"+ftpHost+":"+ftpPort+"/", "");
			String dir = filePath.substring(0, filePath.lastIndexOf("/"));
			String file = filePath.substring(filePath.lastIndexOf("/")+1);

			// 进入文件所在目录,注意编码格式,以能够正确识别中文目录
			ftpClient.changeWorkingDirectory(new String(dir.getBytes("GBK"),FTP.DEFAULT_CONTROL_ENCODING));

			// 检验文件是否存在
			InputStream is = ftpClient.retrieveFileStream(new String(file.getBytes("GBK"),FTP.DEFAULT_CONTROL_ENCODING));
			if(is == null || ftpClient.getReplyCode() == FTPReply.FILE_UNAVAILABLE){
    
    
				return isexist;
			}

			if(is != null){
    
    
				isexist = true;
				is.close();
				ftpClient.completePendingCommand();
			}
			return isexist;
		} catch (Exception e) {
    
    
			logger.error("检验ftp指定路径的文件是否存在失败,message={}",e);
		}
		return isexist;
	}
	/**
	 * ftp服务文件下载到指定目录
	 * @param ftpPath FTP服务器中文件所在路径
	 * @param localPath 下载到本地的位置
	 * @param fileName 文件名称
	 */
	public  void downloadFtpFile(String ftpPath, String localPath,String fileName) throws Exception {
    
    
		//判断文件夹是否存在, 不存在创建
		makeDirs(localPath);
		ftpClient.setControlEncoding("GBK"); // 中文支持
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
		ftpClient.changeWorkingDirectory(StringUtils.trim(ftpPath));
		File file = new File(localPath+"/"+fileName);
		OutputStream os = new FileOutputStream(file);
		ftpClient.retrieveFile(new String(file.getName().getBytes(), "ISO-8859-1"), os);
		os.close();
	}

	/**
	 * 关闭FTP服务器
	 */
	public  void closeServer() {
    
    
		try {
    
    
			if (ftpClient != null) {
    
    
				ftpClient.logout();
				ftpClient.disconnect();
			}
		} catch (IOException e) {
    
    
			logger.error("ftpl连接关闭失败,message={}",e);
		}

	}

	/**
	 * 判断本地路径是否存在,不存在就创建路径
	 */
	public  void makeDirs(String localSavePath) {
    
    
		File localFile = new File(localSavePath);
		if (!localFile.exists()) {
    
    
			localFile.mkdirs();
		}
	}
}

下载到本地,结果:
在这里插入图片描述

二、SFTP是什么?如何实现。

sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的网络的加密方法。sftp 与 ftp 有着几乎一样的语法和功能。SFTP 为 SSH的其中一部分,是一种传输档案至 Blogger 伺服器的安全方式。其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件信息传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接和答复操作,所以从某种意义上来说,SFTP并不像一个服务器程序,而更像是一个客户端程序。SFTP同样是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。(来自百度百科)

1.代码实现

注意:重要的事情说三遍 :::初始化ftp信息,init()方法段逻辑你可以略过,自己去配置连接的参数信息
* 目前我们采用将Sftp连接参数,存在数据库里面了,所以写了一个查询配置信息的方法。


/**
 * SFTP上传下载文件
 */
public class SftpUtils {
    
    
	private final Logger logger = LoggerFactory.getLogger(SftpUtils.class);// SnowLog.getLogger(this.getClass());
	private static String ftpHost; 										// IP
	private static int ftpPort; 										// port
	private static String ftpUserName; 									// 用户
	private static String ftpPassword; 									// 密码


	/**
	 * 连接sftp服务器
	 * @param host 主机
	 * @param port 端口
	 * @param username 用户名
	 * @param password 密码
	 * @return
	 */
	public ChannelSftp connect(String host, int port, String username, String password) {
    
    
		ChannelSftp sftp = null;
		Channel channel=null;
		Session sshSession=null;
		try {
    
    
			JSch jsch = new JSch();
			jsch.getSession(username, host, port);
			sshSession = jsch.getSession(username, host, port);
			if(logger.isInfoEnabled()){
    
    
				logger.info("***************** Session created. **********************");
				logger.info("***************** stf host is "+host+"port is "+port+"  username is "+username+"  password is  "+password+"**********************");
			}
			sshSession.setPassword(password);
			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");
			sshSession.setConfig(sshConfig);
			sshSession.connect();
			if(logger.isInfoEnabled()){
    
    
				logger.info("***************** Session connected. **********************");
				logger.info("***************** Opening Channel. **********************");
			}
			channel = sshSession.openChannel("sftp");
			channel.connect();
			sftp = (ChannelSftp) channel;
			if(logger.isInfoEnabled()){
    
    
				logger.info("***************** Connected to " + host + ". **********************");
			}
		} catch (Throwable e) {
    
    
			if (channel!=null) {
    
    
				try {
    
    
					channel.disconnect();
				}catch(Throwable e1) {
    
    
				}
			}
			
			if (sshSession!=null) {
    
    
				try {
    
    
					sshSession.disconnect();
				}catch(Throwable e1) {
    
    
				}
			}
			
			logger.error(e.getMessage(), e);
		}
		return sftp;
	}
	
	/**
	 * 关闭连接
	 * @param sftp
	 */
	public void disconnect(String host, ChannelSftp sftp){
    
    
		// 关闭连接
		try {
    
    
			if (null != sftp) {
    
    
				sftp.disconnect();
				if(logger.isInfoEnabled()){
    
    
					logger.info("***************** Closing Channel. **********************");
				}
				if (null != sftp.getSession()) {
    
    
					sftp.getSession().disconnect();
					if(logger.isInfoEnabled()){
    
    
						logger.info("***************** Session disconnect. **********************");
					}
				}
			}
			if (logger.isInfoEnabled()) {
    
    
				logger.info("**************** Disconnect to " + host + ". *******************");
			}
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
	}
	
	/**
	 * 判断目录下是否存在文件或者文件夹
	 * @param directory
	 * @param fileName
	 * @param sftp
	 * @return
	 */
	public boolean isExist(String directory, String fileName, ChannelSftp sftp) {
    
    
		try {
    
    
			Vector<LsEntry> v = listFiles(directory, sftp);
			Iterator<LsEntry> it = v.iterator();
			while (it.hasNext()) {
    
    
				LsEntry entry = it.next();
				String flName = entry.getFilename();
				if (flName.equals(fileName)) {
    
    
					return true;
				}
			}
		} catch (SftpException e) {
    
    
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 上传文件
	 * @param directory 上传的目录
	 * @param uploadFile 要上传的文件
	 * @param sftp
	 */
	public String upload(String directory, String uploadFile, ChannelSftp sftp) {
    
    
		String successFlg = "0";
		try {
    
    
			sftp.cd(directory);
			File file = new File(uploadFile);
			sftp.put(new FileInputStream(file), file.getName());
			if(logger.isInfoEnabled()){
    
    
				logger.info("***************** Finished **********************");
			}
		} catch (Exception e) {
    
    
			successFlg = "1";
			e.printStackTrace();
		}
		return successFlg;
	}

	/**
	 * 下载文件
	 * @param directory 下载目录
	 * @param downloadFile 下载的文件
	 * @param saveFile 存在本地的路径
	 * @param sftp
	 */
	public String download(String directory, String downloadFile, String saveFile, ChannelSftp sftp) {
    
    
		String successFlg = "0";
		try {
    
    
			sftp.cd(directory);
			File file = new File(saveFile);
			if(!file.getParentFile().exists()){
    
    
				file.getParentFile().mkdirs();
			}
			sftp.get(downloadFile, new FileOutputStream(file));
			if(logger.isInfoEnabled()){
    
    
				logger.info("***************** Finished **********************");
			}
		} catch (Exception e) {
    
    
			successFlg = "1";
			e.printStackTrace();
		}
		return successFlg;
	}

	/**
	 * 删除文件
	 * @param directory 要删除文件所在目录
	 * @param deleteFile 要删除的文件
	 * @param sftp
	 */
	public void delete(String directory, String deleteFile, ChannelSftp sftp) {
    
    
		try {
    
    
			sftp.cd(directory);
			sftp.rm(deleteFile);
			if(logger.isInfoEnabled()){
    
    
				logger.info("***************** Finished **********************");
			}
			if (null != sftp) {
    
    
				sftp.disconnect();
				if (null != sftp.getSession()) {
    
    
					sftp.getSession().disconnect();
				}
			}
		} catch (Exception e) {
    
    
			e.printStackTrace();
		}
	}

	/**
	 * 列出目录下的文件
	 * @param directory  要列出的目录
	 * @param sftp
	 * @return
	 * @throws SftpException
	 */
	@SuppressWarnings("unchecked")
	public Vector<LsEntry> listFiles(String directory, ChannelSftp sftp) throws SftpException {
    
    
		return sftp.ls(directory);
	}

	/**
	 * 初始化ftp信息,init()方法段逻辑你可以略过,自己去配置连接的参数信息
	 * 目前我们采用将Sftp连接参数,存在数据库里面了,所以写了一个查询配置信息的方法。
	 * @param type
	 * @throws Exception
	 */
	public Map<String,String> init(String type) throws Exception {
    
    
		logger.info("***********************初始化SFTP信息***********************");
		String hostMagicId = "CBS_HOST";
		String userNameMagicId = "CBS_USERNAME";
		String passWordMagicId = "CBS_PASSWORD";
		String cbsPortMagicId="CBS_PORT";
		Map<String, String> hashMap = new HashMap<>();
		TblSysParam selectHost = DBDaos.newInstance().select(TblSysParam.class, "FTP", hostMagicId);
		if (selectHost == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP地址!");
		}
		ftpHost = selectHost.getParamValueTx();
		hashMap.put(hostMagicId,ftpHost);
		TblSysParam selectPort = DBDaos.newInstance().select(TblSysParam.class, "FTP", cbsPortMagicId);
		if (selectPort == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP端口!");
		}
		ftpPort = Integer.parseInt(selectPort.getParamValueTx());
		hashMap.put(cbsPortMagicId, String.valueOf(ftpPort));

		TblSysParam selectUsername = DBDaos.newInstance().select(TblSysParam.class, "FTP", userNameMagicId);
		if (selectUsername == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP用户名!");
		}
		ftpUserName = selectUsername.getParamValueTx();
		hashMap.put(userNameMagicId,ftpUserName);

		TblSysParam selectPassword = DBDaos.newInstance().select(TblSysParam.class, "FTP", passWordMagicId);
		if (selectPassword == null) {
    
    
			SnowExceptionUtil.throwErrorException("请配置FTP密码!");
		}
		ftpPassword = selectPassword.getParamValueTx();
		hashMap.put(passWordMagicId,ftpPassword);
        return hashMap;
	}

	/**
	 * 判断本地路径是否存在,不存在就创建路径
	 */
	public  void makeDirs(String localSavePath) {
    
    
		File localFile = new File(localSavePath);
		if (!localFile.exists()) {
    
    
			localFile.mkdirs();
		}
	}
}

下载文件结果图
在这里插入图片描述


总结

Ftp和Sftp的主要区别就是通信协议不同,Ftp使用的是Tcp协议Sftp使用的是ssh2协议,本身传输的方式是不同的,安全性:Sftp使用加密传输认证信息和传输的数据,所以使用Sftp相对于Ftp是非常安全。
效率:Sftp这种传输方式使用了加密解密技术,所以传输效率比普通的Ftp要低得多——————至此敬我们相关核心系统的朋友们,是他们逼得我学会个很多yyds。

猜你喜欢

转载自blog.csdn.net/zhx__/article/details/119931022