Java連接Sftp判斷文件是否存在,ls、stat、lstat區(qū)別

一、問題背景

目前開發(fā)某個(gè)功能需求時(shí),需要校驗(yàn)sftp中文件是否存在,而不需讀取其內(nèi)容。
公司現(xiàn)有sftp功能代碼都為獲取文件數(shù)據(jù)并落庫或其他處理。
而我這個(gè)功能只需要校驗(yàn)是否存在,不想使用現(xiàn)有方式拉取判斷是否存在,拉取文件必然會(huì)有成本。

二、解決思路

stackover回答:使用 JSch,有沒有辦法判斷遠(yuǎn)程文件是否存在,而無需執(zhí)行l(wèi)s并循環(huán)遍歷文件以查找名稱匹配?

  • ls:查看目錄下文件信息
  • stat:stat方法確實(shí)遵循符號鏈接(即返回鏈接的屬性而不是目標(biāo))
  • lstat:lstat方法不遵循符號鏈接(即返回目標(biāo)的屬性而不是鏈接)
    例如,您有一個(gè)符號鏈接'myhome',它實(shí)際上是/ u02/home/alamba的快捷方式。
    使用lstat,您將獲得鏈接目標(biāo)的屬性'/ u02/home/alamba'文件夾。使用統(tǒng)計(jì)信息,您將獲得“myhome”鏈接的屬性。

還是不太清楚stat和lstat的區(qū)別。網(wǎng)上只找到了以上信息。
不過大致思路就是通過獲取文件信息判斷是否存在,獲取失敗都是拋出異常,自行處理即可。

三、最終解決

  1. 連接sftp獲取對象。調(diào)用其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文件下載失敗,找不到對應(yīng)文件",e);
        } catch (Exception e){
            log.error("Sftp連接獲取文件信息出現(xiàn)未知異常",e);
        }finally {
            if (sftp != null)sftp.quit();
            if (channel != null)channel.disconnect();
            if (session != null)session.disconnect();
        }
        return result;
    }

四、遺留問題

該方法為接口調(diào)用,請求量較大時(shí),與sftp頻繁建立連接勢必會(huì)造成性能、通訊損耗。

甲方封裝代碼
在這里插入圖片描述

個(gè)人淺顯理解:

  1. bean為單例,整個(gè)jvm只有一個(gè)對象共用。
  2. 按照目前的寫法,系統(tǒng)啟動(dòng)或使用時(shí)初始化建立與ftp的鏈接。每次使用時(shí)只調(diào)用其下載或上傳等方法,不能調(diào)用關(guān)閉。
  3. 但目前了解到功能開發(fā)為方法內(nèi)注入該bean,先調(diào)用connect創(chuàng)建鏈接,之后下載,最后close關(guān)閉。
  4. 多線程環(huán)境下,很大可能會(huì)造成A線程關(guān)閉了B新建的鏈接會(huì)話。相當(dāng)于倆線程同時(shí)操作bean內(nèi)的成員變量。

五、附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));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容