对sftp文件上传将行封装,实现连接的单例模式,完成线程安全的改进,sftp文件上传下载失败的重试。
sftp:
ip: 192.168.43.102
port: 22
username: admin
password: admin
downloadSleep: 100 #文件下载失败下次超时重试时间
downloadRetry: 10 #文件下载失败重试次数
uploadSleep: 100 #文件上传失败下次超时重试时间
uploadRettry: 10 #文件上传失败重试次数
包含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;
}
}
是生成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;
}
}
<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>