使用的是springboot的項目,只是貼出主要配置與類,代碼較長,可以先折疊:
參考:https://www.cnblogs.com/xyzq/p/7049369.html
操作工具類SftpUtils:
public class SftpUtils { private static final Logger log = LoggerFactory.getLogger(DownLoadFTPService.class); private String host;// 服務器連接ip private String username;// 用戶名 private String password;// 密碼 private int port = 22;// 端口號 private ChannelSftp sftp = null; private Session sshSession = null; @Value("${sftpTimeOut:0}") private int timeOut; public SftpUtils() { } public SftpUtils(String host, int port, String username, String password) { this.host = host; this.username = username; this.password = password; this.port = port; } public SftpUtils(String host, String username, String password) { this.host = host; this.username = username; this.password = password; } /** * 通過SFTP連接服務器 */ public void connect() { try { JSch jsch = new JSch(); jsch.getSession(username, host, port); sshSession = jsch.getSession(username, host, port); if (log.isInfoEnabled()) { log.info("Session created."); } sshSession.setPassword(password); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); if(0 != timeOut) { sshSession.setTimeout(timeOut); } sshSession.connect(); if (log.isInfoEnabled()) { log.info("Session connected."); } Channel channel = sshSession.openChannel("sftp"); channel.connect(); if (log.isInfoEnabled()) { log.info("Opening Channel."); } sftp = (ChannelSftp) channel; if (log.isInfoEnabled()) { log.info("Connected to " + host + "."); } } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } } /** * 關閉連接 */ public void disconnect() { if (this.sftp != null) { if (this.sftp.isConnected()) { this.sftp.disconnect(); if (log.isInfoEnabled()) { log.info("sftp is closed already"); } } } if (this.sshSession != null) { if (this.sshSession.isConnected()) { this.sshSession.disconnect(); if (log.isInfoEnabled()) { log.info("sshSession is closed already"); } } } } /** * 批量下載文件 * @param remotPath:遠程下載目錄(以路徑符號結束,可以為相對路徑eg:/assess/sftp/jiesuan_2/2014/) * @param localPath:本地保存目錄(以路徑符號結束,D:\\Duansha\\sftp\\) * @return */ public List<String> batchDownLoadFile(String remotePath, String localPath) { return batchDownLoadFile(remotePath, localPath, null, null, false); } /** * 批量下載文件 * * @param remotPath:遠程下載目錄(以路徑符號結束,可以為相對路徑eg:/assess/sftp/jiesuan_2/2014/) * @param localPath:本地保存目錄(以路徑符號結束,D:\\Duansha\\sftp\\) * @param fileFormat:下載文件格式(以特定字符開頭,為空不做檢驗) * @param fileEndFormat:下載文件格式(文件格式,為空不做檢驗) * @param del:下載后是否刪除sftp文件 * @return */ public List<String> batchDownLoadFile(String remotePath, String localPath, String fileFormat, String fileEndFormat, boolean del) { List<String> filenames = new ArrayList<String>(); try { // connect(); Vector<?> v = listFiles(remotePath); // sftp.cd(remotePath); if (v.size() > 0) { //v.size()中包含(. 和 ..)所以實際文件數目=vize-2 log.info("本次處理文件個數不為零,開始下載...fileSize={}", v.size()-2); Iterator<?> it = v.iterator(); while (it.hasNext()) { LsEntry entry = (LsEntry) it.next(); String filename = entry.getFilename(); SftpATTRS attrs = entry.getAttrs(); log.info("filename: {} ", filename); if(".".equals(filename) || "..".equals(filename)) { continue; } if (!attrs.isDir()) { boolean flag = false; String localFileName = localPath + filename; fileFormat = fileFormat == null ? "" : fileFormat.trim(); fileEndFormat = fileEndFormat == null ? "" : fileEndFormat.trim(); // 四種情況 if (fileFormat.length() > 0 && fileEndFormat.length() > 0) { if (filename.startsWith(fileFormat) && filename.endsWith(fileEndFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else if (fileFormat.length() > 0 && "".equals(fileEndFormat)) { if (filename.startsWith(fileFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else if (fileEndFormat.length() > 0 && "".equals(fileFormat)) { if (filename.endsWith(fileEndFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } }else { String newRemotePath = remotePath+ filename+ "/"; String newLocalPath = localPath+ filename+ "\\"; File fi = new File(newLocalPath); if(!fi.exists()) { fi.mkdirs(); } log.info("newRemotePath:{}, newLocalPath:{}", newRemotePath, newLocalPath); batchDownLoadFile(newRemotePath, newLocalPath); } } } if (log.isInfoEnabled()) { log.info("download file is success:remotePath=" + remotePath + "and localPath=" + localPath + ",file size is" + (v.size()-2)); } } catch (SftpException e) { log.error(e.getMessage()); e.printStackTrace(); } finally { // this.disconnect(); } return filenames; } /** * 批量下載文件 * * @param remotPath:遠程下載目錄(以路徑符號結束,可以為相對路徑eg:/assess/sftp/jiesuan_2/2014/) * @param localPath:本地保存目錄(以路徑符號結束,D:\\Duansha\\sftp\\) * @param fileFormat:下載文件格式(以特定字符開頭,為空不做檢驗) * @param fileEndFormat:下載文件格式(文件格式,為空不做檢驗) * @param del:下載后是否刪除sftp文件 * @return */ public List<String> batchDownLoadFileNotDir(String remotePath, String localPath, String fileFormat, String fileEndFormat, boolean del) { List<String> filenames = new ArrayList<String>(); try { // connect(); Vector<?> v = listFiles(remotePath); // sftp.cd(remotePath); if (v.size() > 0) { //v.size()中包含(. 和 ..)所以實際文件數目=vize-2 log.info("本次處理文件個數不為零,開始下載...fileSize={}", v.size()-2); Iterator<?> it = v.iterator(); while (it.hasNext()) { LsEntry entry = (LsEntry) it.next(); String filename = entry.getFilename(); SftpATTRS attrs = entry.getAttrs(); log.info("filename: {} ", filename); if(".".equals(filename) || "..".equals(filename)) { continue; } if (!attrs.isDir()) { boolean flag = false; String localFileName = localPath + filename; fileFormat = fileFormat == null ? "" : fileFormat.trim(); fileEndFormat = fileEndFormat == null ? "" : fileEndFormat.trim(); // 四種情況 if (fileFormat.length() > 0 && fileEndFormat.length() > 0) { if (filename.startsWith(fileFormat) && filename.endsWith(fileEndFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else if (fileFormat.length() > 0 && "".equals(fileEndFormat)) { if (filename.startsWith(fileFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else if (fileEndFormat.length() > 0 && "".equals(fileFormat)) { if (filename.endsWith(fileEndFormat)) { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } } else { flag = downloadFile(remotePath, filename, localPath, filename); if (flag) { filenames.add(localFileName); if (flag && del) { deleteSFTP(remotePath, filename); } } } }else { } } } if (log.isInfoEnabled()) { log.info("download file is success:remotePath=" + remotePath + "and localPath=" + localPath + ",file size is" + (v.size()-2)); } } catch (SftpException e) { log.error(e.getMessage()); e.printStackTrace(); } finally { // this.disconnect(); } return filenames; } /** * 下載單個文件 * * @param remotPath:遠程下載目錄(以路徑符號結束) * @param remoteFileName:下載文件名 * @param localPath:本地保存目錄(以路徑符號結束) * @param localFileName:保存文件名 * @return */ public boolean downloadFile(String remotePath, String remoteFileName, String localPath, String localFileName) { FileOutputStream fieloutput = null; try { // sftp.cd(remotePath); File file = new File(localPath + localFileName); File f = new File(localPath); if(!f.exists()) f.mkdirs(); // if(!file.exists()) { // file.createNewFile(); // }else { // log.info("文件已經下載,不需要重復下載."); // return true; // } fieloutput = new FileOutputStream(file); sftp.get(remotePath + remoteFileName, fieloutput); if (log.isInfoEnabled()) { log.info("- - - - - DownloadFile: " + remoteFileName + " success from sftp."); } return true; } catch (FileNotFoundException e) { log.error(e.getMessage()); e.printStackTrace(); } catch (SftpException e) { log.error(e.getMessage()); e.printStackTrace(); } finally { if (null != fieloutput) { try { fieloutput.close(); } catch (IOException e) { log.error(e.getMessage()); e.printStackTrace(); } } } return false; } /** * 上傳單個文件 * * @param remotePath:遠程保存目錄 * @param remoteFileName:保存文件名 * @param localPath:本地上傳目錄(以路徑符號結束) * @param localFileName:上傳的文件名 * @return */ public boolean uploadFile(String remotePath, String remoteFileName, String localPath, String localFileName) { FileInputStream in = null; try { createDir(remotePath); File file = new File(localPath + localFileName); in = new FileInputStream(file); sftp.put(in, remoteFileName); return true; } catch (FileNotFoundException e) { log.error(e.getMessage()); e.printStackTrace(); } catch (SftpException e) { log.error(e.getMessage()); e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e) { log.error(e.getMessage()); e.printStackTrace(); } } } return false; } /** * 批量上傳文件 * * @param remotePath:遠程保存目錄 * @param localPath:本地上傳目錄(以路徑符號結束) * @param del:上傳后是否刪除本地文件 * @return */ public boolean bacthUploadFile(String remotePath, String localPath, boolean del) { try { connect(); File file = new File(localPath); log.info("file: {} ", file); File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isFile() && files[i].getName().indexOf("bak") == -1) { if (this.uploadFile(remotePath, files[i].getName(), localPath, files[i].getName()) && del) { deleteFile(localPath + files[i].getName()); } } } if (log.isInfoEnabled()) { log.info("upload file is success:remotePath=" + remotePath + "and localPath=" + localPath + ",file size is " + files.length); } return true; } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } finally { this.disconnect(); } return false; } /** * 刪除本地文件 * * @param filePath * @return */ public boolean deleteFile(String filePath) { File file = new File(filePath); if (!file.exists()) { return false; } if (!file.isFile()) { return false; } boolean rs = file.delete(); if (rs && log.isInfoEnabled()) { log.info("delete file success from local."); } return rs; } /** * 創建目錄 * * @param createpath * @return */ public boolean createDir(String createpath) { try { if (isDirExist(createpath)) { this.sftp.cd(createpath); return true; } String pathArry[] = createpath.split("/"); StringBuffer filePath = new StringBuffer("/"); for (String path : pathArry) { if (path.equals("")) { continue; } filePath.append(path + "/"); if (isDirExist(filePath.toString())) { sftp.cd(filePath.toString()); } else { // 建立目錄 sftp.mkdir(filePath.toString()); // 進入並設置為當前目錄 sftp.cd(filePath.toString()); } } this.sftp.cd(createpath); return true; } catch (SftpException e) { log.error(e.getMessage()); e.printStackTrace(); } return false; } /** * 判斷目錄是否存在 * * @param directory * @return */ public boolean isDirExist(String directory) { boolean isDirExistFlag = false; try { SftpATTRS sftpATTRS = sftp.lstat(directory); isDirExistFlag = true; return sftpATTRS.isDir(); } catch (Exception e) { log.error(e.getMessage()); if (e.getMessage().toLowerCase().equals("no such file")) { isDirExistFlag = false; } } return isDirExistFlag; } /** * 刪除stfp文件 * * @param directory:要刪除文件所在目錄 * @param deleteFile:要刪除的文件 * @param sftp */ public void deleteSFTP(String directory, String deleteFile) { try { // sftp.cd(directory); sftp.rm(directory + deleteFile); if (log.isInfoEnabled()) { log.info("delete file success from sftp."); } } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } } /** * 如果目錄不存在就創建目錄 * * @param path */ public void mkdirs(String path) { File f = new File(path); String fs = f.getParent(); f = new File(fs); if (!f.exists()) { f.mkdirs(); } } /** * 列出目錄下的文件 * * @param directory:要列出的目錄 * @param sftp * @return * @throws SftpException */ public Vector<?> listFiles(String directory) throws SftpException { log.info("listFiles:{}",directory); return sftp.ls(directory); } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public ChannelSftp getSftp() { return sftp; } public void setSftp(ChannelSftp sftp) { this.sftp = sftp; } /** 測試 */ public static void main(String[] args) { SftpUtils sftp = null; // 本地存放地址 String localPath = "M:\\"; // Sftp下載路徑 String sftpPath = "/usr/etc/"; try { sftp = new SftpUtils("172.168.65.171", "root", "root1234"); sftp.connect(); // 下載 sftp.batchDownLoadFile(sftpPath, localPath, "error", null, false); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } finally { sftp.disconnect(); } } /** 錯誤處理: 1. java.security.NoSuchAlgorithmException: DH KeyPairGenerator not available 復制sunjce_provider.jar(jre/lib/ext/)到lib下。 */ }
sftp實體SftpFileInfo:
使用:
配置文件配置:
#ip sftpIpConfig: ip #用戶名 sftpUsernameConfig: xxx #密碼 sftpPasswordConfig: xxx #遠程服務器文件路徑 remotePathConfig: /qq/ww/ee/
#遠程服務器文件路徑 remotePathConfig: /qq/ww/ee/ #本地保存路徑 localPathConfig: D:\\
class中使用:
@Value("${sftpIpConfig:}")
private String sftpIpConfig;
@Value("${sftpUsernameConfig:}")
private String sftpUsernameConfig;
@Value("${sftpPasswordConfig:}")
private String sftpPasswordConfig;
@Value("${localPathConfig:}")
private String localPathConfig;
其中的配置也可以使用參數傳入,如果配置固定不經常改的時候可以使用配置文件也比較方便。
使用sftpUtils:
SftpUtils sftp = null; sftp = new SftpUtils(sftpFileInfo.getSftpIp(), sftpFileInfo.getSftpUsername(),sftpFileInfo.getSftpPassword()); sftp.connect();
之后的操作就是看實際情況,使用的都是SftpUtils.class中的方法了。
