本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《
最近公司有个数据对接需求,合作方那边是使用我们这边的系统进行出单的,数据首先也是在我们这边。后面他们自己开发了业务系统,需要我们这边定时把每天的数据传送到那边去。他们那边开发部门要求我们这边,按一定的格式导出加签加密的数据文件到他们的sftp服务器上面去。sftp代码之前同事有写过类似的代码,就把他的给我啦,既然有了代码,当然要消化成自己的知识啦!这个过程中也遇到一些坑,就是我们上传到sftp目录的时候,文件一多我们就得隔开文件夹,一般都是按年月隔开的,但是sftp切换目录后,如果目录不存在,我们就新建目录,这样的逻辑是没毛病,但是它没办法一次建多级目录,比如/home 下面可以建/home/2022/ 没办法建/home/2022/03(会报异常),所以这个的话我们还得用循环来做。
一、代码
先给大家看下代码:
String userName = "";//账号
String password = ""; //密码
String host = ""; //ip
int port=8889; //端口号
String sftpUrl = "/application/data"; //上传到sftp服务器 路径
String publicUrl = "E://"; //要上传的文件
String yyyy = DateUtils.formatDate(new Date(), "yyyy");
String mm = DateUtils.formatDate(new Date(), "MM");
String uploadUrl = sftpUrl + "/" + yyyy + "/" + mm;
//存储目录地址
List dirs = new ArrayList();
dirs.add(0, sftpUrl + "/" + yyyy + "/");
dirs.add(1, sftpUrl + "/" + yyyy + "/" + mm + "/");
try {
//1.获取会话
JSch jSch = new JSch();
Session session = jSch.getSession(userName, host, port);
session.setPassword(password);
Properties properties = new Properties();
properties.put("StrictHostKeyChecking", "no");
session.setConfig(properties);
session.connect();
//2.获取上传的管道
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
if (!(uploadUrl == null || uploadUrl.trim().length() == 0)) {
for (int index = 0; index < dirs.size(); index++) {
//目录不存在,新建目录
try {
sftp.cd(uploadUrl);//进入指定目录
break;
} catch (SftpException e1) {
try {
sftp.cd(dirs.get(index).toString());
} catch (SftpException e2) {
try {
sftp.mkdir(dirs.get(index).toString());
sftp.cd(dirs.get(index).toString());
} catch (SftpException e3) {
logger.error("SFTP切换目录出错!", e3);
//读取源文件流(客户端文件)
InputStream client_fileInput = new FileInputStream(publicUrl );
sftp.put(client_fileInput, “上传后的文件名”);
//传送到服务端
//5.关闭
sftp.disconnect();
client_fileInput.close();
channel.disconnect();
session.disconnect();
logger.info("sftp传输成功");
} catch (Exception e) {
logger.info("sftp传输失败: " + e.toString());
e.printStackTrace();
一般上传完文件后,需要删除本地的文件以免占用空间
/**
* 迭代删除文件夹
* @param dirPath 文件夹路径
public static void deleteDir(String dirPath) {
File file = new File(dirPath);
if(!file.exists()){
return;
if(file.isFile())
file.delete();
}else {
File[] files = file.listFiles();
if(files == null) {
file.delete();
}else {
for (int i = 0; i < files.length; i++) {
deleteDir(files[i].getAbsolutePath());
file.delete();
这里我遇到个坑,就是你们发现文件夹或者文件没删除或者没删除干净,就要检查一下流有没有关闭,传递流的时候最好不要直接 xxx方法(new FileInputStream),用下面这种方式比较好,好排查问题,哈哈。
FileInputStream file=new FileInputStream(“”); xxx方法(file);file.close();
二、sftp连接过程
2.1、 JSch简介
JSch库可以实现Java连接
Linux服务器
并操作命令、文件等,支持常用的各种授权模式。
从JSch对象中获取Session,用于连接,并设置连接信息,账号、密码、服务器地址、端口号。
通过以上的步骤,我们与sftp服务器建立了连接后,我们需要获取文件的传输通道Channel,并指定为sftp服务,随便进行connect()连接。
获取了sftp通道,我们可以类似在linux下简单做一些shell指令操作:
mkdir()方法 创建目录,只允许创建一级目录
cd()方法 切换目录
put()方法 上传文件
rm()方法 删除文件
还有很多,大家可以直接看对象的对应方法就知道了,方法命名跟我们平时用的linux命令差不多。