對sftp文件上傳將行封裝,實現連接的單例模式,完成線程安全的改進,sftp文件上傳下載失敗的重試。
application.yml配置文件
sftp: ip: 192.168.43.102 port: 22 username: admin password: admin downloadSleep: 100 #文件下載失敗下次超時重試時間 downloadRetry: 10 #文件下載失敗重試次數 uploadSleep: 100 #文件上傳失敗下次超時重試時間 uploadRettry: 10 #文件上傳失敗重試次數
SFTPClientUtils.java
包含sftp文件上傳的一些基本方法,單個上傳,批量下載,單個文件下載
@Component @ConfigurationProperties(prefix = "sftp") public class SFTPClientUtils { private static int downloadSleep; private static int downloadRetry; private static int uploadSleep; private static int uploadRettry; private static Logger LOGGER = LoggerFactory.getLogger(SFTPClientUtils.class); /** * 文件上傳 * 將文件對象上傳到sftp作爲文件。文件完整路徑=basePath+directory * 目錄不存在則會上傳文件夾 * @param basePath 服務器的基礎路徑 * @param directory 上傳到該目錄 * @param sftpFileName sftp端文件名 * @param file 文件對象 */ public synchronized static boolean upload(String basePath,String directory, String filePath){ boolean result = false; Integer i = 0; while(!result){ ChannelSftp sftp = SFTPConnectionFactory.getInstance().makeConnection(); try { sftp.cd(basePath); sftp.cd(directory); } catch (SftpException e) { LOGGER.info("sftp文件上傳,目錄不存在開始創建"); String [] dirs=directory.split("/"); String tempPath=basePath; for(String dir:dirs){ if(null== dir || "".equals(dir)) continue; tempPath+="/"+dir; try{ sftp.cd(tempPath); }catch(SftpException ex){ try { sftp.mkdir(tempPath); sftp.cd(tempPath); } catch (SftpException e1) { LOGGER.error("sftp文件上傳,目錄創建失敗,錯誤信息:"+e1.getMessage()+ex.getMessage()); } } } } try { File file = new File(filePath); sftp.put(new FileInputStream(file) , file.getName()); if(i>0){ LOGGER.info("sftp重試文件上傳成功,ftp路徑:"+basePath+directory+",文件名稱:"+file.getName()); }else{ LOGGER.info("sftp文件上傳成功,ftp路徑爲"+basePath+directory+",文件名稱:"+file.getName()); } result = true; } catch (Exception e) { i++; LOGGER.error("sftp文件上傳失敗,重試中。。。第"+i+"次,錯誤信息"+e.getMessage()); if(i>uploadRettry){ LOGGER.error("sftp文件上傳失敗,超過重試次數結束重試,錯誤信息"+e.getMessage()); return result; } try { TimeUnit.MILLISECONDS.sleep(uploadSleep); } catch (InterruptedException e1) { e1.printStackTrace(); } } } return result; } /** * 下載文件。 * @param directory 下載目錄 * @param downloadFile 下載的文件 * @param saveFile 存在本地的路徑 */ public synchronized static boolean download(String directory, String downloadFile, String saveFile){ boolean result = false; Integer i = 0; while(!result){ ChannelSftp sftp = SFTPConnectionFactory.getInstance().makeConnection(); if (directory != null && !"".equals(directory)) { try { sftp.cd(directory); } catch (SftpException e) { LOGGER.error("sftp文件下載,目錄不存在,錯誤信息"+e.getMessage()); } } File file = new File(saveFile+downloadFile); FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(file); } catch (FileNotFoundException e1) { LOGGER.error("sftp文件下載失敗,本地目錄不存在"+e1.getMessage()); } try { sftp.get(downloadFile, fileOutputStream); if(i>0){ LOGGER.info("sftp文件重試下載成功,sftp地址:"+directory+",本地文件地址:"+saveFile); }else{ LOGGER.info("sftp文件下載成功,sftp地址:"+directory+",本地文件地址:"+saveFile); } result = true; } catch (SftpException e1) { i++; LOGGER.error("sftp文件下載失敗,重試中。。。第"+i+"次,錯誤信息"+e1.getMessage()); if(i>downloadRetry){ LOGGER.error("ftp文件下載失敗,超過重試次數結束重試,錯誤信息"+e1.getMessage()); return result; } try { TimeUnit.MILLISECONDS.sleep(downloadSleep); } catch (Exception e2) { e2.printStackTrace(); } }finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } /** * 刪除文件 * @param directory 要刪除文件所在目錄 * @param deleteFile 要刪除的文件 */ public synchronized static boolean delete(String directory, String deleteFile){ boolean result = false; ChannelSftp sftp = SFTPConnectionFactory.getInstance().makeConnection(); try { sftp.cd(directory); sftp.rm(deleteFile); } catch (SftpException e) { // TODO Auto-generated catch block e.printStackTrace(); } result = true; return result; } public static int getDownloadSleep() { return downloadSleep; } public static void setDownloadSleep(int downloadSleep) { SFTPClientUtils.downloadSleep = downloadSleep; } public static int getDownloadRetry() { return downloadRetry; } public static void setDownloadRetry(int downloadRetry) { SFTPClientUtils.downloadRetry = downloadRetry; } public static int getUploadSleep() { return uploadSleep; } public static void setUploadSleep(int uploadSleep) { SFTPClientUtils.uploadSleep = uploadSleep; } public static int getUploadRettry() { return uploadRettry; } public static void setUploadRettry(int uploadRettry) { SFTPClientUtils.uploadRettry = uploadRettry; } }
SFTPConnectionFactory.java
是生成sftp上傳對象的工場類
/** * SFTP工廠類,用於獲取SFTP的連接 * @author 奇點_ */ @Component @ConfigurationProperties(prefix = "sftp") public class SFTPConnectionFactory { private static Logger LOGGER = LoggerFactory.getLogger(FTPClientUtils.class); /** SFTP 登錄用戶名*/ private static String username; /** SFTP 登錄密碼*/ private static String password; /** 私鑰 */ private static String privateKey; /** SFTP 服務器地址IP地址*/ private static String ip; /** SFTP 端口*/ private static int port; private static final SFTPConnectionFactory factory = new SFTPConnectionFactory(); private ChannelSftp client; private Session session; private SFTPConnectionFactory(){ } public static SFTPConnectionFactory getInstance(){ return factory; } synchronized public ChannelSftp makeConnection(){ if(client==null||session==null||!client.isConnected()||!session.isConnected()){ try { JSch jsch = new JSch(); if (privateKey != null) { jsch.addIdentity(privateKey);// 設置私鑰 } session = jsch.getSession(username, ip, port); if (password != null) { session.setPassword(password); } Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); client = (ChannelSftp) channel; LOGGER.info("sftp服務器連接成功"); } catch (JSchException e) { LOGGER.error("sftp登錄失敗,檢測登錄ip,端口號,用戶名密碼是否正確,錯誤信息爲"+e.getMessage()); } } return client; } /** * 關閉連接 server */ public void logout(){ if (client != null) { if (client.isConnected()) { client.disconnect(); } } if (session != null) { if (session.isConnected()) { session.disconnect(); } } } public static String getUsername() { return username; } public static void setUsername(String username) { SFTPConnectionFactory.username = username; } public static String getPassword() { return password; } public static void setPassword(String password) { SFTPConnectionFactory.password = password; } public static String getPrivateKey() { return privateKey; } public static void setPrivateKey(String privateKey) { SFTPConnectionFactory.privateKey = privateKey; } public static String getIp() { return ip; } public static void setIp(String ip) { SFTPConnectionFactory.ip = ip; } public static int getPort() { return port; } public static void setPort(int port) { SFTPConnectionFactory.port = port; } }
pom.xml 依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>fakepath</groupId> <artifactId>ftp4j</artifactId> <version>1.7.2</version> </dependency> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.54</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies>