一、Java实现对SFTP服务器的文件的上传下载

1、添加maven依赖:

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>

2、SFTPUtils工具类:

package neimeng;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Properties;
import java.util.Vector;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;


/**
 * @author Administrator
 *
 */
@Component
public class SftpUtils {
    
    private final static Logger logger = LoggerFactory.getLogger(SftpUtils.class);

    protected final static int CLIENT_TIMEOUT = 1000 * 180;
    
    public SftpUtils(){
        
    }

    /**
     * 连接sftp服务器
     */
    public static ChannelSftp login(String host, int port, String username, String password) {
    	logger.info("SftpUtils login begin");
    	Session session = null;
        try {
            JSch jSch = new JSch();
            session = jSch.getSession(username, host, port);
            session.setTimeout(CLIENT_TIMEOUT);
            
            if (!StringUtils.isEmpty(password)) {
               session.setPassword(Base64Utils.decodeFromString(password)); 
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            
            session.setConfig(config);
            session.connect();
            
            Channel channel = session.openChannel("sftp");  
            channel.connect();  
            
            ChannelSftp sftp = (ChannelSftp) channel;

            logger.info("SftpUtils login end");
            return sftp;
        } catch (JSchException e) {
            logger.error("连接SFTP服务器失败", e);
            throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCP.setExceptionMsg("连接SFTP服务器失败"));
        }  
    }
    
    /** 
     * 关闭连接 server  
     */  
    public static void logout(ChannelSftp sftp){  
    	logger.info("SftpUtils logout begin");
        if (sftp != null) {  
            Session session = null;
			try {
				session = sftp.getSession();
				if (sftp.isConnected()) {  
					sftp.disconnect();  
				}
			} catch (JSchException e) {
				logger.error("获取session失败", e);
			} finally {
				if (session != null) {
					session.disconnect(); 
				}
			}
        }  
        logger.info("SftpUtils logout end");
    }  

    /**  
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     * @param basePath  服务器的基础路径 
     * @param directory  上传到该目录  
     * @param sftpFileName  sftp端文件名  
     * @param in   输入流  
     */  
    public static boolean upload(String host, int port, String username, String password, String basePath, String sftpFileName, InputStream input) {  
    	logger.info("SftpUtils upload begin");
    	boolean success = true;
    	ChannelSftp sftp = login(host, port, username, password);
        try {   
            sftp.cd(basePath);
        } catch (SftpException e) { 
            //目录不存在,则创建文件夹
            String [] dirs = basePath.split("/");
            String tempPath = "";
            for(String dir:dirs){
                if(null== dir || "".equals(dir)) {
                    continue;
                }
                tempPath+="/"+dir;
                try {
                    sftp.cd(tempPath);
                } catch (SftpException e1) {
                    try {
                        sftp.mkdir(tempPath);
                        sftp.cd(tempPath);
                    } catch (SftpException e2) {
                        logger.error("创建文件夹失败", e2);
                        throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCP.setExceptionMsg("创建文件夹失败"));
                    }
                }
                try{ 
                    sftp.cd(tempPath);
                }catch(SftpException e1){
                    logger.error("SFTP服务器异常", e1);
                    throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCP.setExceptionMsg("SFTP服务器异常"));
                }
            }
        }  
        try {
            //上传文件
            sftp.put(input, sftpFileName);
        } catch (SftpException e) {
            // TODO Auto-generated catch block
            logger.error("上传文件失败", e);
//            throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCP.setExceptionMsg("上传文件失败"));
            success = false;
        } finally {
			logout(sftp);
		}
        logger.info("SftpUtils upload end");
        return success;
    } 

    /** 
     * 下载文件。
     * @param directory 下载目录  
     * @param downloadFile 下载的文件 
     * @param saveFile 存在本地的路径 
     */    
    public static boolean download(String host, int port, String username, String password, String filePath, final OutputStream outputStream) {  
    	logger.info("SftpUtils download begin");
    	boolean downloaded = true;
    	ChannelSftp sftp = login(host, port, username, password);
    	String fileName = null;
        try {
            if (filePath != null && !"".equals(filePath)) {  
            	String directory = filePath.substring(0, filePath.lastIndexOf(File.separator));
                sftp.cd(directory);  
            }  
            fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
            
            sftp.get(fileName, outputStream);
        } catch (SftpException e) {
        	downloaded = false;
            logger.error("FTP服务器异常", e);
//            throw new BusinessException(ExceptionEnum.EXECUTE_RUNTIME_EXCP.setExceptionMsg("FTP服务器异常"));
        } finally {
			logout(sftp);
		}
        logger.info("SftpUtils download end");
        return downloaded;
    }
    
    /** 
     * 删除文件 
     * @param directory 要删除文件所在目录 
     * @param deleteFile 要删除的文件 
     */  
    public static boolean delete(String host, int port, String username, String password, String filePath){  
    	logger.info("SftpUtils delete begin");
    	boolean success = true;
    	ChannelSftp sftp = null;
    	try {
			sftp = login(host, port, username, password);
			String directory = filePath.substring(0, filePath.lastIndexOf(File.separator));
			sftp.cd(directory);
			String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
			sftp.rm(fileName);
		} catch (SftpException e) {
			logger.error("文件删除失败", e);
			success = false;
		} finally {
			logout(sftp);
		}
        logger.info("SftpUtils delete end");
        return success;
    }  

    /** 
     * 列出目录下的文件 
     * @param directory 要列出的目录 
     * @param sftp 
     */  
    public static boolean isFileExist(String host, int port, String username, String password, String filePath) {  
    	boolean success = false;
    	ChannelSftp sftp = null;
		try {
			sftp = login(host, port, username, password);
			String directory = filePath.substring(0, filePath.lastIndexOf(File.separator));
			String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
			Vector<?> vector = sftp.ls(directory);
			for (Object obj : vector) {
				if (obj != null) {
					LsEntry lsEntry = (LsEntry) obj;
					if (fileName.equals(lsEntry.getFilename())) {
						success = true;
						break;
					}
				}
			}
		} catch (Exception e) {
			logger.error("sftp服务器异常");
		} finally {
			logout(sftp);
		}
    	return success;  
    }  

}

二、Java实现对FTP服务器的文件的上传下载

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
 
/**
 * ftp上传下载工具类
 */
public class FtpUtil {
 
	/** 
	 * Description: 向FTP服务器上传文件 
	 * @param host FTP服务器hostname 
	 * @param port FTP服务器端口 
	 * @param username FTP登录账号 
	 * @param password FTP登录密码 
	 * @param basePath FTP服务器基础目录
	 * @param filePath FTP服务器文件存放路径。文件的路径为basePath+filePath
	 * @param filename 上传到FTP服务器上的文件名 
	 * @param input 输入流 
	 * @return 成功返回true,否则返回false 
	 */  
	public static boolean uploadFile(String host, int port, String username, String password, String basePath,
			String filePath, String filename, InputStream input) {
		boolean result = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;
			ftp.connect(host, port);// 连接FTP服务器
			// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
			ftp.login(username, password);// 登录
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return result;
			}
			//切换到上传目录
			if (!ftp.changeWorkingDirectory(basePath+filePath)) {
				//如果目录不存在创建目录
				String[] dirs = filePath.split("/");
				String tempPath = basePath;
				for (String dir : dirs) {
					if (null == dir || "".equals(dir)) continue;
					tempPath += "/" + dir;
					if (!ftp.changeWorkingDirectory(tempPath)) {  //进不去目录,说明该目录不存在
						if (!ftp.makeDirectory(tempPath)) { //创建目录
							//如果创建文件目录失败,则返回
							System.out.println("创建文件目录"+tempPath+"失败");
							return result;
						} else {
							//目录存在,则直接进入该目录
							ftp.changeWorkingDirectory(tempPath);	
						}
					}
				}
			}
			//设置上传文件的类型为二进制类型
			ftp.setFileType(FTP.BINARY_FILE_TYPE);
			//上传文件
			if (!ftp.storeFile(filename, input)) {
				return result;
			}
			input.close();
			ftp.logout();
			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return result;
	}
	
	/** 
	 * Description: 从FTP服务器下载文件 
	 * @param host FTP服务器hostname 
	 * @param port FTP服务器端口 
	 * @param username FTP登录账号 
	 * @param password FTP登录密码 
	 * @param remotePath FTP服务器上的相对路径 
	 * @param fileName 要下载的文件名 
	 * @param localPath 下载后保存到本地的路径 
	 * @return 
	 */  
	public static boolean downloadFile(String host, int port, String username, String password, String remotePath,
			String fileName, String localPath) {
		boolean result = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;
			ftp.connect(host, port);
			// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
			ftp.login(username, password);// 登录
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return result;
			}
			ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
			FTPFile[] fs = ftp.listFiles();
			for (FTPFile ff : fs) {
				if (ff.getName().equals(fileName)) {
					File localFile = new File(localPath + "/" + ff.getName());
 
					OutputStream is = new FileOutputStream(localFile);
					ftp.retrieveFile(ff.getName(), is);
					is.close();
				}
			}
 
			ftp.logout();
			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return result;
	}
 
	//ftp上传文件测试main函数
	public static void main(String[] args) {
		try {  
	        FileInputStream in=new FileInputStream(new File("D:\\Tomcat 5.5\\pictures\\t0176ee418172932841.jpg"));  
	        boolean flag = uploadFile("192.168.111.128", 21, "用户名", "密码", "/www/images","/2017/11/19", "hello.jpg", in);  
	        System.out.println(flag);  
	    } catch (FileNotFoundException e) {  
	        e.printStackTrace();  
	    }  
	}
}

//用于判断ftp是否连接
public static boolean connect (final String hostname, final int port, final String username, final String password) {
        final FTPClient ftpClient = new FTPClient(); 
        boolean connect = true;
        try {
            ftpClient.connect(hostname, port);
            log.info("-----username: " + username + " password: " + new String(Base64Utils.decodeFromString(password)));
            connect = ftpClient.login(username, new String(Base64Utils.decodeFromString(password)));
            log.info("-----" + connect);
        } catch (SocketException e) {
            log.error("connect ftp failed", e);
            connect = false;
        } catch (IOException e) {
            log.error("login ftp failed", e);
            connect = false;
        } finally {
            if (ftpClient != null) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    log.error("ftp disconnect failed", e);
                }
            }
        }
        return connect;
}

有时系统可能要兼容ftp和sftp,而ftp的端口一般是21,sftp对应的端口是22,因此只要增加对端口的判断就可以实现ftp和sftp的兼容了。

import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.ChannelSftp;;

public class FtpAndSftpUtils {
	
	private final static Logger logger = LoggerFactory.getLogger(FtpAndSftpUtils.class);
	
	//用于判断ftp是否连接
    public static boolean connect (final String hostname, final int port, final String username, final String password) {
    	boolean connect = true;
    	if (port == 21) {
    		//采用ftp连接方式
    		connect = FtpUtils.connect(hostname, port, username, password);
    	} else {
    		//采用sftp连接方式
    		ChannelSftp sftp = SftpUtils.login(hostname, port, username, password);
    		if (sftp == null) {
    			connect = false;
    		} else {
    			SftpUtils.logout(sftp);
    		}
    	}
        return connect;
    }
	
    //上传文件
    public static boolean uploadFile(final String hostname, final int port, final String username, final String password,
    		final String fileName, final String path ,final InputStream in) {
    	boolean success = false;
    	if (port == 21) {
    		success = FtpUtils.uploadFile(hostname, port, username, password, fileName, path, in);
    	} else {
    		success = SftpUtils.upload(hostname, port, username, password, path, fileName, in);
    	}
    	return success;
    }
    
    //下载文件
    public static boolean downloadFile(final String hostname, final int port, final String username,
            final String password, final String path, final OutputStream os) {
    	boolean success = false;
    	if (port == 21) {
    		success = FtpUtils.downloadFile(hostname, port, username, password, path, os);
    	} else {
    		success = SftpUtils.download(hostname, port, username, password, path, os);
    	}
    	return success;
    }
    
    //删除文件
    public static boolean deleteFile(final String hostname, final int port, final String username, final String password, final String path) {
    	boolean success = true;
    	if (port == 21) {
    		success = FtpUtils.deleteFile(hostname, port, username, password, path);
    	} else {
    		success = SftpUtils.delete(hostname, port, username, password, path);
    	}
    	return success;
    }

    //判断文件在指定目录是否存在
	public static boolean isFTPFileExist(final String hostname, final Integer port, final String username, final String password, final String filePath) {
		boolean success = true;
		if (port == 21) {
			success = FtpUtils.isFTPFileExist(hostname, port, username, password, filePath);
		} else {
			success = SftpUtils.isFileExist(hostname, port, username, password, filePath);
		}
		return success;
	}
}