Java连接Sftp判断文件是否存在,ls、stat、lstat区别

一、问题背景

目前开发某个功能需求时,需要校验sftp中文件是否存在,而不需读取其内容。
公司现有sftp功能代码都为获取文件数据并落库或其他处理。
而我这个功能只需要校验是否存在,不想使用现有方式拉取判断是否存在,拉取文件必然会有成本。

二、解决思路

stackover回答:使用 JSch,有没有办法判断远程文件是否存在,而无需执行ls并循环遍历文件以查找名称匹配?

  • ls:查看目录下文件信息
  • stat:stat方法确实遵循符号链接(即返回链接的属性而不是目标)
  • lstat:lstat方法不遵循符号链接(即返回目标的属性而不是链接)
    例如,您有一个符号链接'myhome',它实际上是/ u02/home/alamba的快捷方式。
    使用lstat,您将获得链接目标的属性'/ u02/home/alamba'文件夹。使用统计信息,您将获得“myhome”链接的属性。

还是不太清楚stat和lstat的区别。网上只找到了以上信息。
不过大致思路就是通过获取文件信息判断是否存在,获取失败都是抛出异常,自行处理即可。

三、最终解决

  1. 连接sftp获取对象。调用其lstat方法传入文件全路径。
  2. 抛出异常说明获取不到,正常返回文件信息。
  3. 其他方式,只需将sftp.lstat换为.stat或.ls即可。
    public boolean isExistSftp(String filePach){
        boolean result = false;
        Session session = null;
        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(apolo.getSftpUserName(),apolo.getSftpIp(), apolo.getSftpPort());
            session.setPassword(apolo.getSftpPassWord());
            session.setTimeout(60000);
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            channel = session.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            SftpATTRS lstat = sftp.lstat(filePach);
            result = true;
        } catch (JSchException e) {
            log.error("连接SFTP失败,IP:{},端口:{},用户名:{},密码:{}",
                    apolo.getSftpIp(),apolo.getSftpPort(),apolo.getSftpUserName(),apolo.getSftpPassWord().substring(0,3),e);
        } catch (SftpException e) {
            log.error("sftp文件下载失败,找不到对应文件",e);
        } catch (Exception e){
            log.error("Sftp连接获取文件信息出现未知异常",e);
        }finally {
            if (sftp != null)sftp.quit();
            if (channel != null)channel.disconnect();
            if (session != null)session.disconnect();
        }
        return result;
    }

四、遗留问题

该方法为接口调用,请求量较大时,与sftp频繁建立连接势必会造成性能、通讯损耗。

甲方封装代码
在这里插入图片描述

个人浅显理解:

  1. bean为单例,整个jvm只有一个对象共用。
  2. 按照目前的写法,系统启动或使用时初始化建立与ftp的链接。每次使用时只调用其下载或上传等方法,不能调用关闭。
  3. 但目前了解到功能开发为方法内注入该bean,先调用connect创建链接,之后下载,最后close关闭。
  4. 多线程环境下,很大可能会造成A线程关闭了B新建的链接会话。相当于俩线程同时操作bean内的成员变量。

五、附ftp连接

该部分引入:https://www.ktanx.com/blog/p/4028

减少依赖,使用JDK自带的ftp客户端sun.net.ftp.FtpClient

FtpClient ftpClient = new FtpClient();
ftpClient.openServer(FTP_IP, FTP_PORT);
ftpClient.login(LOGIN_NAME, PASSWORD);
ftpClient.binary();
TelnetInputStream is = ftpClient.get("/ftp/re/20140713.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

apache的commons-net

FtpClient ftpClient = new FtpClient();
ftpClient.connect(FTP_IP, FTP_PORT);
ftpClient.login(LOGIN_NAME, PASSWORD);
// 中文支持
ftpClient.setControlEncoding("UTF-8");   
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);  
ftpClient.enterLocalPassiveMode();  
  InputStream is = ftpClient.retrieveFileStream("/ftp/re/20140713.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

sftp

ChannelSftp sftp = null;
JSch jsch = new JSch();
Session sshSession = jsch.getSession(LOGIN_NAME, FTP_IP, FTP_PORT);
sshSession.setPassword(PASSWORD);
sshSession.setConfig("StrictHostKeyChecking", "no");
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
InputStream is = sftp.get("/ftp/re/20140713.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容