packagexxx.utilsimport com.jcraft.jsch.*
importorg.slf4j.Loggerimportorg.slf4j.LoggerFactoryimportjava.text.SimpleDateFormat
//使用的是groovyclassSftpUtil {private static final Logger logger =LoggerFactory.getLogger(SftpUtil.getClass())static SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd")
JSch jsch= nullSession session= nullChannelSftp channel= null
static ThreadLocal sftpLocal = new ThreadLocal()
SftpUtil(String userName, String host,intport, String password) {
connect(userName, host, port, password)
}
SftpUtil(String userName, String host,intport, String password, String keyFilePath, String passphrase) {
connect(userName, host, port, password, keyFilePath, passphrase)
}booleanisConnected() {return null != channel &&channel.isConnected()
}static SftpUtil getSftpUtil(String userName, String host, int port, String password) throwsException {
SftpUtil sftpUtils=sftpLocal.get()if (sftpUtils == null || !sftpUtils.isConnected()) {
sftpLocal.set(newSftpUtil(userName, host, port, password))
}returnsftpLocal.get()
}static SftpUtil getSftpUtil(String userName, String host, int port, String password, String keyFilePath, String passphrase) throwsException {
SftpUtil sftpUtils=sftpLocal.get()if (sftpUtils == null || !sftpUtils.isConnected()) {
sftpLocal.set(newSftpUtil(userName, host, port, password, keyFilePath, passphrase))
}returnsftpLocal.get()
}static voidrelease() {if (null !=sftpLocal.get()) {
sftpLocal.get().close()
sftpLocal.set(null)
}
}/*** 连接到指定的IP
*
*@throwsJSchException*/ChannelSftp connect(String userName, String host,intport, String password) {try{
jsch= new JSch()//创建JSch对象
session = jsch.getSession(userName, host, port)//根据用户名、主机ip、端口号获取一个Session对象
session.setConfig("PreferredAuthentications", "password")
session.setPassword(password)
session.setConfig("StrictHostKeyChecking", "no")
session.setTimeout(60000)
session.setServerAliveInterval(2000)
session.setServerAliveCountMax(8)
session.connect(3000)
logger.info("sftp session connected.")
channel= (ChannelSftp) session.openChannel("sftp")
channel.connect(3000)
logger.info("Connected successfully ${host} ${userName}")
}catch(JSchException e) {
logger.error("sftp connected failed...", e)
}
}/*** 密钥连接到指定的IP
*
*@throwsJSchException
*@paramkeyFilePath 密钥路径
*@parampassphrase 密钥的密码*/
public void connect(String userName, String host, int port, String password, String keyFilePath, String passphrase) throwsException {try{
jsch= newJSch();if (keyFilePath != null) {if (passphrase != null) {
jsch.addIdentity(keyFilePath, passphrase);//设置私钥
} else{
jsch.addIdentity(keyFilePath);//设置私钥
}
logger.info("连接sftp,私钥文件路径:" +keyFilePath);
}
logger.info("SFTP Host: " + host + "; UserName:" +userName);
session=jsch.getSession(userName, host, port);
logger.debug("Session 已建立.");if (password != null) {
session.setPassword(password);
}
Properties sshConfig= newProperties();
sshConfig.put("StrictHostKeyChecking", "no");
session.setConfig(sshConfig);
session.setConfig("kex", "diffie-hellman-group1-sha1");
session.connect();
logger.debug("Session 已连接.");
channel= (ChannelSftp) session.openChannel("sftp")
channel.connect(3000)
logger.info("连接到SFTP成功.Host: " +host);
}catch(Exception e) {
logger.error("连接SFTP失败:", e);
}
}/*** 关闭连接*/
voidclose() {if (channel != null) {try{
channel.disconnect()
}catch(Exception e) {
logger.error("sftp close channel failed...", e)
}
}if (session != null) {try{
session.disconnect()
}catch(Exception e) {
logger.error("sftp close session failed...", e)
}
}
}/*** 执行相关的命令,
* 但是部分情况不可用
*
*@throwsJSchException*/String execCmd(String command)throwsJSchException {
BufferedReader reader= nullString result= ""
if (channel == null) {
logger.info("SFTP服务器未连接")returnresult
}try{if (command != null) {
((ChannelExec) channel).setCommand(command)
channel.connect()
InputStream input=channel.getInputStream()
reader= new BufferedReader(newInputStreamReader(input))
String buf= null
while ((buf = reader.readLine()) != null) {
logger.info(buf)
result+=buf
}
}
}catch(IOException e) {
logger.error("远程服务器端IO流错误:" +e.getMessage())
e.printStackTrace()
}catch(JSchException e) {
logger.error("Jsch传输异常:" +e.getMessage())
e.printStackTrace()
}finally{try{
reader.close()
}catch(IOException e) {
logger.error("远程服务器端IO流关闭失败:" +e.getMessage())
e.printStackTrace()
}
}
result
}/*** 上传文件
*
*@paramfileName
* 上传的文件,含扩展名
*@paramftpPath
* 文件本地目录
*@paramoutFilePath
* 文件上传目录
*@throwsJSchException*@throwsFileNotFoundException* 上传本地最新文件,并备份服务器端原文件*/
void upload(String fileName, String localPath, String outFilePath) throwsException {//连接sftp
if (channel == null) {
logger.info("SFTP服务器未连接")
release()return}
String localFilepath= localPath +fileName
File localFile= newFile(localFilepath)
FileInputStream input= null
try{if (!localFile.exists()) {
logger.warn("本地服务器:上传文件不存在")return}if(existFile(outFilePath, fileName)) {return}
String uploadFile= outFilePath + fileName //上传的文件
logger.info("上传文件:" + fileName + "开始")
input= newFileInputStream(localFile)
channel.put(input, uploadFile, ChannelSftp.OVERWRITE)
logger.info("上传到sftp成功")//上传完成,备份本地文件
String localBak =bakFileName(fileName)
String bakPath=bakPath(localPath, fileName)
File newfile= new File(bakPath +localBak)if(localFile.renameTo(newfile)) {
logger.info("本地文件备份成功:" +localBak)
}else{
logger.info("本地文件备份失败:" +localBak)
}
}catch(Exception e) {
logger.info("上传文件:" + fileName + "失败")throwe
}finally{if(input) {
input.close()
}
release()
}
}/*** 上传文件某文件夹下所有文件
*
*@paramfileName
* 上传的文件,含扩展名
*@paramftpPath
* 文件本地目录
*@paramoutFilePath
* 文件上传目录
*@throwsJSchException*@throwsFileNotFoundException**/
void uploadAllFile(String fileName, String localPath, String outFilePath, String bakPath) throwsException {//连接sftp
if (channel == null) {
logger.info("SFTP服务器未连接")
release()return}
File[] files=[]
File localFile= newFile(localPath)
FileInputStream input= nullList ins =[]try{if (!localFile.exists()) {
logger.warn("本地服务器:上传文件不存在")return}if(existFile(outFilePath, fileName)) {return}if(localFile.isDirectory()) {
files=localFile.listFiles();if (files == null || files.length <= 0) {return;
}for(File f : files) {
String uploadFile= outFilePath + f.getName() //上传的文件
logger.info("上传文件:" + f.getName() + "开始")
input= newFileInputStream(f)
ins.add(input)
channel.put(input, uploadFile, ChannelSftp.OVERWRITE)
logger.info("上传到sftp成功")
}
}
logger.info(files.size()+"---------------------------------------")
}catch(Exception e) {
logger.info("上传文件:" + fileName + "失败")throwe
}finally{
ins?.each {it.close()}if(input) {
input.close()
}
release()//上传完成,备份本地文件
if(bakPath) {
files?.each { it.renameTo(new File(bakPath+bakFileName(it.getName()))) }
}else{
files?.each {logger.info("删除文件:" + it.getName() + "--:"+it.delete())}
}
}
}/*** 下载文件
* 备份本地文件,再下载服务器端最新文件
*@paramlocalPath 本地存放路径
*@paramremotePath 服务器端存放路径
*@throwsJSchException*/
void download(String fileName, String localPath, String remotePath) throwsException {//src linux服务器文件地址,dst 本地存放地址
if (channel == null) {
logger.info("SFTP服务器未连接")return}
String remoteFile= remotePath +fileName
String localFile= localPath +fileName
FileOutputStream output=null
try{if (!existFile(remotePath, fileName)) {
logger.warn("SFTP服务器:下载文件不存在" + remotePath +fileName)return}
File file= newFile(localFile)if (file.size() > 0) {//创建新名字的抽象文件
String bakname =bakFileName(fileName)
String bakPath=bakPath(localPath, fileName)
File newfile= new File(bakPath +bakname)if(file.renameTo(newfile)) {
logger.info("本地文件:" + fileName + "备份成功")
}else{
logger.info("本地文件:" + fileName + "备份失败,将覆盖原文件!")
}
}
output= newFileOutputStream(file)
logger.info("下载文件:" + fileName + "开始")
channel.get(remoteFile, output)
logger.info("下载文件:" + fileName + "成功")//下载完成后备份服务器文件
String bakFile =bakFileName(fileName)
String bakRemotePath=bakPath(remotePath, fileName)//channel.rename(remoteFile, bakRemotePath + fileName)//delete(remotePath, fileName)
logger.info("服务器端文件备份成功:" +bakFile)
}catch(Exception e) {
logger.info("下载文件:" + fileName + "失败")throwe
}finally{if(output) {
output.close()
}
release()
}
}/*** 删除文件
*
*@paramdirectory
* 要删除文件所在目录
*@paramdeleteFile
* 要删除的文件
*@throwsJSchException*/
void delete(String directory, String deleteFile) throwsException {if (channel == null) {
logger.info("SFTP服务器未连接")return}
channel.cd(directory)
channel.rm(deleteFile)
logger.info("删除成功")
}/*** 列出目录下的文件
*
*@paramdirectory
* 要列出的目录
*@paramsftp
*@return*@throwsJSchException*/@SuppressWarnings("rawtypes")
Vector listFiles(String directory)throwsException {if (channel == null) {
logger.info("SFTP服务器未连接")return null}
Vector vector=channel.ls(directory)returnvector
}/*** 判断文件是否存在
*@paramsourceName
*@return
*/Boolean existFile(String remotrPath, String filename) {
Vector files=listFiles(remotrPath)
Boolean rst= falsefiles.each {
ChannelSftp.LsEntry entry=(ChannelSftp.LsEntry) itif (entry.getFilename() ==filename) {
rst= true}
}
rst
}
String bakFileName(String sourceName) {return sourceName + "." + df.format(new Date()) +System.currentTimeMillis().toString()
}
String bakPath(String outFilePath, String fileName) {
List names = fileName.split(".csv").toList()if (outFilePath.lastIndexOf("/") != -1) {return outFilePath.substring(0, outFilePath.lastIndexOf("/"))+ "bak/"}else if (outFilePath.lastIndexOf("\\") != -1) {return outFilePath.substring(0, outFilePath.lastIndexOf("\\"))+ "bak\\"}return outFilePath + "bak/"}
}