发布于2026-07-17 阅读(0)
扫一扫,手机访问
前阵子接了个数据对接的需求,合作方那边要用我们系统出单,数据自然先落我们这边。后来他们自己搞了业务系统,要求我们定时把每天的数据传过去。开发部门那边提了个要求:按指定格式导出加签加密的数据文件,放到他们的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();
JSch这个库,可以让你用Ja va连接Linux服务器,操作命令、文件什么的,支持常见的各种授权模式。
从JSch对象中获取Session,用于连接,设置账号、密码、服务器地址、端口号。
StrictHostKeyChecking=no 最不安全的级别,当然也没有那么多烦人的提示了,相对安全的内网测试时建议使用。如果连接server的key在本地不存在,那么就自动添加到文件中(默认是known_hosts),并且给出一个警告。 StrictHostKeyChecking=ask 默认的级别。如果连接和key不匹配,给出提示,并拒绝登录。 StrictHostKeyChecking=yes 最安全的级别,如果连接与key不匹配,就拒绝连接,不会提示详细信息。
建立连接后,需要获取文件传输通道Channel,指定为sftp服务,然后调用connect()。
获取sftp通道后,可以像在Linux下一样,执行一些简单的shell指令:
mkdir()方法 创建目录,只允许创建一级目录cd()方法 切换目录put()方法 上传文件rm()方法 删除文件还有更多方法,直接看对象的API就行,命名风格跟Linux命令差不多。
用完一定要记得关闭各种连接和流!
从实际项目来看,这些步骤基本能覆盖大部分场景。关键还是那几点:目录逐级创建、流正确关闭、连接及时释放。希望这段分享对你有帮助。
下一篇:Golang健康检查接口的实现
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8