配置maven
<dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.54</version> </dependency>
工具類
package com.sftp;import com.jcraft.jsch.*; import com.jcraft.jsch.ChannelSftp.LsEntry; import org.apache.log4j.Logger;import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Vector;/*** SFTP(Secure File Transfer Protocol),安全文件傳送協議。*/ public class Sftp {/** 日志記錄器 */private Logger logger = Logger.getLogger(Sftp.class);/** Session */private Session session = null;/** Channel */private ChannelSftp channel = null;/** SFTP服務器IP地址 */private String host;/** SFTP服務器端口 */private int port;/** 連接超時時間,單位毫秒 */private int timeout;/** 用戶名 */private String username;/** 密碼 */private String password;/*** SFTP 安全文件傳送協議* @param host SFTP服務器IP地址* @param port SFTP服務器端口* @param timeout 連接超時時間,單位毫秒 * @param username 用戶名* @param password 密碼*/public Sftp(String host,int port,int timeout,String username,String password){this.host = host;this.port = port;this.timeout = timeout;this.username = username;this.password = password;}/*** 登陸SFTP服務器* @return boolean*/public boolean login() {try {JSch jsch = new JSch();session = jsch.getSession(username, host, port);if(password != null){session.setPassword(password);}Properties config = new Properties();config.put("StrictHostKeyChecking", "no");session.setConfig(config);session.setTimeout(timeout);session.connect();logger.debug("sftp session connected");logger.debug("opening channel");channel = (ChannelSftp)session.openChannel("sftp");channel.connect();logger.debug("connected successfully");return true;} catch (JSchException e) {logger.error("sftp login failed",e);return false;}}/*** 上傳文件* <p>* 使用示例,SFTP服務器上的目錄結構如下:/testA/testA_B/* <table border="1">* <tr><td>當前目錄</td><td>方法</td><td>參數:絕對路徑/相對路徑</td><td>上傳后</td></tr>* <tr><td>/</td><td>uploadFile("testA","upload.txt",new FileInputStream(new File("up.txt")))</td><td>相對路徑</td><td>/testA/upload.txt</td></tr>* <tr><td>/</td><td>uploadFile("testA/testA_B","upload.txt",new FileInputStream(new File("up.txt")))</td><td>相對路徑</td><td>/testA/testA_B/upload.txt</td></tr>* <tr><td>/</td><td>uploadFile("/testA/testA_B","upload.txt",new FileInputStream(new File("up.txt")))</td><td>絕對路徑</td><td>/testA/testA_B/upload.txt</td></tr>* </table>* </p>* @param pathName SFTP服務器目錄* @param fileName 服務器上保存的文件名* @param input 輸入文件流* @return boolean*/public boolean uploadFile(String pathName,String fileName,InputStream input){String currentDir = currentDir();if(!changeDir(pathName)){return false;}try {channel.put(input,fileName,ChannelSftp.OVERWRITE);if(!existFile(fileName)){logger.debug("upload failed");return false;}logger.debug("upload successful");return true;} catch (SftpException e) {logger.error("upload failed",e);return false;} finally {changeDir(currentDir);}}/*** 上傳文件* <p>* 使用示例,SFTP服務器上的目錄結構如下:/testA/testA_B/* <table border="1">* <tr><td>當前目錄</td><td>方法</td><td>參數:絕對路徑/相對路徑</td><td>上傳后</td></tr>* <tr><td>/</td><td>uploadFile("testA","upload.txt","up.txt")</td><td>相對路徑</td><td>/testA/upload.txt</td></tr>* <tr><td>/</td><td>uploadFile("testA/testA_B","upload.txt","up.txt")</td><td>相對路徑</td><td>/testA/testA_B/upload.txt</td></tr>* <tr><td>/</td><td>uploadFile("/testA/testA_B","upload.txt","up.txt")</td><td>絕對路徑</td><td>/testA/testA_B/upload.txt</td></tr>* </table>* </p>* @param pathName SFTP服務器目錄* @param fileName 服務器上保存的文件名* @param localFile 本地文件* @return boolean*/public boolean uploadFile(String pathName,String fileName,String localFile){String currentDir = currentDir();if(!changeDir(pathName)){return false;}try {channel.put(localFile,fileName,ChannelSftp.OVERWRITE);if(!existFile(fileName)){logger.debug("upload failed");return false;}logger.debug("upload successful");return true;} catch (SftpException e) {logger.error("upload failed",e);return false;} finally {changeDir(currentDir);}}/*** 下載文件* <p>* 使用示例,SFTP服務器上的目錄結構如下:/testA/testA_B/* <table border="1">* <tr><td>當前目錄</td><td>方法</td><td>參數:絕對路徑/相對路徑</td><td>下載后</td></tr>* <tr><td>/</td><td>downloadFile("testA","down.txt","D:\\downDir")</td><td>相對路徑</td><td>D:\\downDir\\down.txt</td></tr>* <tr><td>/</td><td>downloadFile("testA/testA_B","down.txt","D:\\downDir")</td><td>相對路徑</td><td>D:\\downDir\\down.txt</td></tr>* <tr><td>/</td><td>downloadFile("/testA/testA_B","down.txt","D:\\downDir")</td><td>絕對路徑</td><td>D:\\downDir\\down.txt</td></tr>* </table>* </p>* @param remotePath SFTP服務器目錄* @param fileName 服務器上需要下載的文件名* @param localPath 本地保存路徑* @return boolean*/public boolean downloadFile(String remotePath,String fileName,String localPath){String currentDir = currentDir();if(!changeDir(remotePath)){return false;}try {String localFilePath = localPath + File.separator + fileName;channel.get(fileName,localFilePath);File localFile = new File(localFilePath);if(!localFile.exists()){logger.debug("download file failed");return false;}logger.debug("download successful");return true;} catch (SftpException e) {logger.error("download file failed",e);return false;} finally {changeDir(currentDir);}}/*** 切換工作目錄* <p>* 使用示例,SFTP服務器上的目錄結構如下:/testA/testA_B/* <table border="1">* <tr><td>當前目錄</td><td>方法</td><td>參數(絕對路徑/相對路徑)</td><td>切換后的目錄</td></tr>* <tr><td>/</td><td>changeDir("testA")</td><td>相對路徑</td><td>/testA/</td></tr>* <tr><td>/</td><td>changeDir("testA/testA_B")</td><td>相對路徑</td><td>/testA/testA_B/</td></tr>* <tr><td>/</td><td>changeDir("/testA")</td><td>絕對路徑</td><td>/testA/</td></tr>* <tr><td>/testA/testA_B/</td><td>changeDir("/testA")</td><td>絕對路徑</td><td>/testA/</td></tr>* </table>* </p>* @param pathName 路徑* @return boolean*/public boolean changeDir(String pathName){if(pathName == null || pathName.trim().equals("")){logger.debug("invalid pathName");return false;}try {channel.cd(pathName.replaceAll("\\\\", "/"));logger.debug("directory successfully changed,current dir=" + channel.pwd());return true;} catch (SftpException e) {logger.error("failed to change directory",e);return false;}}/*** 切換到上一級目錄* <p>* 使用示例,SFTP服務器上的目錄結構如下:/testA/testA_B/* <table border="1">* <tr><td>當前目錄</td><td>方法</td><td>切換后的目錄</td></tr>* <tr><td>/testA/</td><td>changeToParentDir()</td><td>/</td></tr>* <tr><td>/testA/testA_B/</td><td>changeToParentDir()</td><td>/testA/</td></tr>* </table>* </p>* @return boolean*/public boolean changeToParentDir(){return changeDir("..");}/*** 切換到根目錄* @return boolean*/public boolean changeToHomeDir(){String homeDir = null;try {homeDir = channel.getHome();} catch (SftpException e) {logger.error("can not get home directory",e);return false;}return changeDir(homeDir);}/*** 創建目錄* <p>* 使用示例,SFTP服務器上的目錄結構如下:/testA/testA_B/* <table border="1">* <tr><td>當前目錄</td><td>方法</td><td>參數(絕對路徑/相對路徑)</td><td>創建成功后的目錄</td></tr>* <tr><td>/testA/testA_B/</td><td>makeDir("testA_B_C")</td><td>相對路徑</td><td>/testA/testA_B/testA_B_C/</td></tr>* <tr><td>/</td><td>makeDir("/testA/testA_B/testA_B_D")</td><td>絕對路徑</td><td>/testA/testA_B/testA_B_D/</td></tr>* </table>* <br/>* <b>注意</b>,當<b>中間目錄不存在</b>的情況下,不能夠使用絕對路徑的方式期望創建中間目錄及目標目錄。* 例如makeDir("/testNOEXIST1/testNOEXIST2/testNOEXIST3"),這是錯誤的。* </p>* @param dirName 目錄* @return boolean*/public boolean makeDir(String dirName){try {channel.mkdir(dirName);logger.debug("directory successfully created,dir=" + dirName);return true;} catch (SftpException e) {logger.error("failed to create directory", e);return false;}}/*** 刪除文件夾* @param dirName* @return boolean*/@SuppressWarnings("unchecked")public boolean delDir(String dirName){if(!changeDir(dirName)){return false;}Vector<LsEntry> list = null;try {list = channel.ls(channel.pwd());} catch (SftpException e) {logger.error("can not list directory",e);return false;}for(LsEntry entry : list){String fileName = entry.getFilename();if(!fileName.equals(".") && !fileName.equals("..")){if(entry.getAttrs().isDir()){delDir(fileName);} else {delFile(fileName);}}}if(!changeToParentDir()){return false;}try {channel.rmdir(dirName);logger.debug("directory " + dirName + " successfully deleted");return true;} catch (SftpException e) {logger.error("failed to delete directory " + dirName,e);return false;}}/*** 刪除文件* @param fileName 文件名* @return boolean*/public boolean delFile(String fileName){if(fileName == null || fileName.trim().equals("")){logger.debug("invalid filename");return false;}try {channel.rm(fileName);logger.debug("file " + fileName + " successfully deleted");return true;} catch (SftpException e) {logger.error("failed to delete file " + fileName,e);return false;}}/*** 當前目錄下文件及文件夾名稱列表* @return String[]*/public String[] ls(){return list(Filter.ALL);}/*** 指定目錄下文件及文件夾名稱列表* @return String[]*/public String[] ls(String pathName){String currentDir = currentDir();if(!changeDir(pathName)){return new String[0];};String[] result = list(Filter.ALL);if(!changeDir(currentDir)){return new String[0];}return result;}/*** 當前目錄下文件名稱列表* @return String[]*/public String[] lsFiles(){return list(Filter.FILE);}/*** 指定目錄下文件名稱列表* @return String[]*/public String[] lsFiles(String pathName){String currentDir = currentDir();if(!changeDir(pathName)){return new String[0];};String[] result = list(Filter.FILE);if(!changeDir(currentDir)){return new String[0];}return result;}/*** 當前目錄下文件夾名稱列表* @return String[]*/public String[] lsDirs(){return list(Filter.DIR);}/*** 指定目錄下文件夾名稱列表* @return String[]*/public String[] lsDirs(String pathName){String currentDir = currentDir();if(!changeDir(pathName)){return new String[0];};String[] result = list(Filter.DIR);if(!changeDir(currentDir)){return new String[0];}return result;}/*** 當前目錄是否存在文件或文件夾* @param name 名稱* @return boolean*/public boolean exist(String name){return exist(ls(), name);}/*** 指定目錄下,是否存在文件或文件夾* @param path 目錄* @param name 名稱* @return boolean*/public boolean exist(String path,String name){return exist(ls(path),name);}/*** 當前目錄是否存在文件* @param name 文件名* @return boolean*/public boolean existFile(String name){return exist(lsFiles(),name);}/*** 指定目錄下,是否存在文件* @param path 目錄* @param name 文件名* @return boolean*/public boolean existFile(String path,String name){return exist(lsFiles(path), name);}/*** 當前目錄是否存在文件夾* @param name 文件夾名稱* @return boolean*/public boolean existDir(String name){return exist(lsDirs(), name);}/*** 指定目錄下,是否存在文件夾* @param path 目錄* @param name 文家夾名稱* @return boolean*/public boolean existDir(String path,String name){return exist(lsDirs(path), name);}/*** 當前工作目錄* @return String*/public String currentDir(){try {return channel.pwd();} catch (SftpException e) {logger.error("failed to get current dir",e);return homeDir();}}/*** 登出*/public void logout(){if(channel != null){channel.quit();channel.disconnect();}if(session != null){session.disconnect();}logger.debug("logout successfully");}//------private method ------/** 枚舉,用于過濾文件和文件夾 */private enum Filter {/** 文件及文件夾 */ ALL ,/** 文件 */ FILE ,/** 文件夾 */ DIR };/*** 列出當前目錄下的文件及文件夾* @param filter 過濾參數* @return String[]*/@SuppressWarnings("unchecked")private String[] list(Filter filter){Vector<LsEntry> list = null;try {//ls方法會返回兩個特殊的目錄,當前目錄(.)和父目錄(..)list = channel.ls(channel.pwd());} catch (SftpException e) {logger.error("can not list directory",e);return new String[0];}List<String> resultList = new ArrayList<String>();for(LsEntry entry : list){if(filter(entry, filter)){resultList.add(entry.getFilename());}}return resultList.toArray(new String[0]);}/*** 判斷是否是否過濾條件* @param entry LsEntry* @param f 過濾參數* @return boolean*/private boolean filter(LsEntry entry,Filter f){if(f.equals(Filter.ALL)){return !entry.getFilename().equals(".") && !entry.getFilename().equals("..");} else if(f.equals(Filter.FILE)){return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && !entry.getAttrs().isDir();} else if(f.equals(Filter.DIR)){return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && entry.getAttrs().isDir();}return false;}/*** 根目錄* @return String*/private String homeDir(){try {return channel.getHome();} catch (SftpException e) {return "/";}}/*** 判斷字符串是否存在于數組中* @param strArr 字符串數組* @param str 字符串* @return boolean*/private boolean exist(String[] strArr,String str){if(strArr == null || strArr.length == 0){return false;}if(str == null || str.trim().equals("")){return false;}for(String s : strArr){if(s.equalsIgnoreCase(str)){return true;}}return false;}}
?