SFTPUtils工具类及使用

配置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;}}

 

转载于:https://www.cnblogs.com/xiaofengfree/p/10309839.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国内手机产业混乱:产业一窝蜂 企业捞快钱

对于当前国内手机行业的现状&#xff0c;本报记者采访的多位业内人士表示&#xff0c;目前国内手机行业仍是“红海”格局&#xff0c;多数企业并不了解手机产业规律&#xff0c;看到有钱赚就“一窝蜂”上项目。有行业人士认为&#xff0c;要走出目前行业的现状&#xff0c;企业…

查看私密文章方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我只是记录下&#xff0c;曾经写过一次文章&#xff0c;勾选了私密&#xff0c;再后来就找不到了。 下面这个链接可以查出那篇文章&…

SDUT-3364_欧拉回路

数据结构实验之图论八&#xff1a;欧拉回路 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 在哥尼斯堡的一个公园里&#xff0c;有七座桥将普雷格尔河中两个岛及岛与河岸连接起来。 能否走过这样的七座桥&#xff0c;并且每桥只走一次&#xff1f;瑞士数学…

Tcp三次握手和四次挥手状态图

三次握手 四次挥手 正常情况下 同时挥手 SYN攻击&#xff1a; 在三次握手过程中&#xff0c;Server发送SYN-ACK之后&#xff0c;收到Client的ACK之前的TCP连接称为半连接&#xff08;half-open connect&#xff09;&#xff0c;此时Server处于SYN_RCVD状态&#xff0c;当…

QEMU 3.0.0 新特性一览

QEMU 在 2018年8月15发布了版本3.0.0&#xff0c; 正式从 2.12 进入了3.0 时代。 而且到今年位为止&#xff0c;QEMU 已经有15个年头了&#xff0c;出乎意料的长阿&#xff0c;:) 其主要新特性如下&#xff1a; ARM&#xff1a; 在virt机器中支持SMMUv3 IOMMU 在v8M中支持VLLDM…

OpenCL、OpenGL 同时工作

视频处理如果能使用OpenCL、OpenGL、omap将大量提高运算速度&#xff0c;简单介绍OpenCL、OpenGL 同时工作。 OpenCL和OpenGL都能用于操作GPU&#xff0c;但是前者主要用于通用计算&#xff0c;而后者主要用于图像渲染。在某些情况下&#xff0c;我们希望能用OpenCL计得到算图像…

财务自由之路——为什么选择淘宝(下)

接上文~一、淘宝之前的大佬们是怎么试错的?我们看看在淘宝之前的大佬们是怎么试错迭代产品的。都知道飞机是莱特兄弟发明的&#xff0c;但很少有人知道为什么是他们。在内燃机发明后的很长一段时间内全球各地发明家都在投入研究飞机&#xff0c;莱特兄弟相对于其他竞争者&…

java参数后面跟三个点是什么意思

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 AVA中类型后面跟三个点是什么来的。 看代码中那个三点&#xff0c;这样做起到重载的作用&#xff0c;但这是什么意思&#xff1f; cla…

一只视频程序猿的移动直播SDK初体验

本文转自一只视频程序猿的移动直播SDK初体验&#xff0c;此处仅做排版改动。 今早老板召开站会&#xff0c;“移动直播这么火&#xff0c;市面上有一百多个APP&#xff0c;小斌&#xff0c;你下周交个原型APP瞅瞅!” 小弟心中一万匹草泥马奔过&#xff0c;这玩意儿哪儿是几天就…

Xilinx zynq-7000系列FPGA移植Linux操作系统详细教程

Xilinx zynq-7000系列FPGA移植Linux操作系统详细教程 一&#xff1a;前言 最近手上压了一块米联客的Miz7035&#xff0c;一块xilinx zynq-7000系列的开发板&#xff0c;想着正好学习一下linux在ARM9上的移植&#xff0c;网上基本都是ZC702、zed的教程&#xff0c;这对于买了非标…

程序员的创业困境 谁来帮助出出主意?

【编者按】有人说&#xff0c;程序员是吃青春饭的&#xff0c;到一定年龄就得考虑转行&#xff0c;也有人选择自己创业。而当创业使你偏离了之前持续学习专业知识的轨道时&#xff0c;你会选择在创业路上继续坚持还是回归自己的老本行&#xff1f;编程编了十几年的Dan McComas半…

节选—Android 视频直播 ( 从快播到直播,从高清到无码 )十年视频开发项目

本文转载自Android 视频直播 &#xff08; 从快播到直播&#xff0c;从高清到无码 )十年视频开发项目&#xff0c;截取其中技术概念比较相关的部分&#xff0c;并做了重新的排版。 视频和直播的准备&#xff1a; android-java层&#xff1a;camera相关&#xff08;视频&#x…

getDeclaredMethod和getMethod的区别

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 getDeclaredMethod*()获取的是类自身声明的所有方法&#xff0c;包含public、protected和private方法。getMethod*()获取的是类的所有共有…

12.5PMP试题每日一题

在什么情况下项目正式受控于实施整体变更控制过程&#xff1a;A、从项目启动到收尾的所有过程B、只有当项目基准建立之后C、在项目基准建立之前D、只要有人提起变更请求的时候 作者&#xff1a;Tracy19890201&#xff08;同微信号&#xff09; 答案将于明天和新题一起揭晓&…

在线预览word,excel文档

Google Doc 示例&#xff1a;https://jsfiddle.net/7xr419yb/ Microsoft Office 示例&#xff1a;https://jsfiddle.net/gcuzq343/转载于:https://www.cnblogs.com/alexguoyihao/p/10314626.html

如何迁移整个git仓库

转自准备更换git托管&#xff0c;如何迁移原git仓库一个回答 如果你想从别的 Git 托管服务那里复制一份源代码到新的 Git 托管服务器上的话&#xff0c;可以通过以下步骤来操作。 从原地址克隆一份裸版本库&#xff0c;比如原本托管于 GitHub。 git clone –bare git://githu…

关于创业:希望有人在N年前就告诉我的一些事儿

【编者按】原文作者为前微软员工、创业家Amir Khella&#xff0c;他离开微软后开始自主创业&#xff0c;并成功创办了多家公司。他经常在博客中分享自己的创业故事和经验。以下是其中一篇博文&#xff0c;他认为创业者想要成功&#xff0c;首先需要找到自己的方向&#xff0c;再…

Rust核心团队前成员Brian Anderson加入PingCAP

昨天&#xff0c;国内新型分布式数据库公司PingCAP联合创始人兼CEO刘奇在朋友圈宣布&#xff0c;Rust核心团队前成员Brian Anderson将加入公司。PingCAP联合创始人兼CTO黄东旭进一步向InfoQ记者证实了此消息&#xff0c;并透露Brian将从事TiKV相关的工作&#xff0c;从存储引擎…

JeeSite 是什么、概述

见JeeSite官网&#xff1a;http://jeesite4.mydoc.io/ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 总体概述 快速访问 JeeSite 官网地址&#xff1a;http://jeesite.comJeeSite 在…

单机单网卡最大tcp长连接数真的是65535吗?

很早微博上一直讨论比较多的问题&#xff0c;这里转载个知乎的答案&#xff1a;单机单网卡最大tcp长连接数真的是65535吗&#xff1f; 作者&#xff1a;许怀远 链接&#xff1a;https://www.zhihu.com/question/66553828/answer/244313925 来源&#xff1a;知乎 著作权归作者…