java 连接远程Linux服务器并读取文件获取文件流

前言

项目中需要从一台服务器调取其他Linux服务器上的文件,并上传到其他服务器接口中;用的是通过文件流上传;

主要是用的: session.execCommand(str) 和session.getStdout() 来获取读取到的文件流;

开始一直读取不到文件的实际大小,一直是0字节;

后来在两个方法之间加了休眠,但实际运行中,还有部分文件没有获取到实际大小,还是0字节;

再后来又优化了一下,应该是都读取成功了。

如果读取的文件过大、或者网络不好,建议加大休眠时间试试。

---------------------------------------------------------2020.06.09优化-----------------------------------------------------------

程序运行了数周后,对接方有反馈文件大小不一致,经排查,好像最终上传时文件流中的大小还不是实际文件的大小,可能只读取了一部分就开始上传了;

优化后的方案是:先执行命令获取文件大小,再用命令获取文件流,对比文件的大小还流的大小,一致时再往下执行。

一、依赖

<dependency>
   <groupId>com.trilead</groupId>
   <artifactId>trilead-ssh2</artifactId>
   <version>1.0.0-build222</version>
</dependency>

二、代码

/**
     * 获取conn
     * @param ip
     * @param port
     * @param user
     * @param pwd
     * @return
     */
    private static Connection getConn(String ip, int port, String user, String pwd) {
        Connection conn = new Connection(ip, port);
        if(conn.isAuthenticationComplete()) {
            return conn;
        }
        try {
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(user, pwd);
            if(!isAuthenticated) {
                throw new BaseException("authentication failed!");
            }
            return conn;
        } catch (Exception e) {
            log.error("Connect error:", e);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取session
     * @param conn
     * @return
     * @throws IOException
     */
    public static Session getSession(Connection conn) throws IOException{
        Session session = conn.openSession();
        return session;
    }

    /**
     * 获取SFTPv3Client
     * @param conn
     * @return
     * @throws IOException
     */
    public static SFTPv3Client getClient(Connection conn) throws IOException {
        SFTPv3Client client = new SFTPv3Client(conn);
        return client;
    }

1.主要方法:

/**
     * 读取远端文件流
     * @param filePath
     * @return
     * @throws IOException
     */
    private static InputStream readFile(Connection conn, String filePath, String ip) throws IOException, InterruptedException {
        Session session = getSession(conn);
        //获取文件大小
        session.execCommand("du -b ".concat(filePath));
        InputStream sizeIn = new StreamGobbler(session.getStdout());
        //将字节流向字符流的转换。
        InputStreamReader isr = new InputStreamReader(sizeIn);//读取
        //创建字符流缓冲区
        BufferedReader bufr = new BufferedReader(isr);//缓冲
        String line;
        int fileSize = 0;
        while((line = bufr.readLine())!=null){
            String[] fileAttr = line.split("\t");
            fileSize = Integer.parseInt(fileAttr[0]);
        }
        isr.close();
        session.close();
        log.info("          【" + ip + "】【文件大小】" + fileSize);


        session = getSession(conn);
        session.execCommand("cat ".concat(filePath));
        //休眠2秒再获取返回信息,防止网络传输过程中延迟造成读取文件大小为0字节
        //Thread.sleep(2000);
        InputStream is = new StreamGobbler(session.getStdout());
        session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
        //获取指令是否成功执行:0-成功,非0-失败.
        //int ret = session.getExitStatus();
        //log.info("          【" + ip + "】【命令执行结果】" + (0 == ret ? "---成功---" : "====失败===="));
        log.info("          【" + ip + "】【获取到当前文件流为】" + is.available());
        int i = 0;
        while (fileSize != is.available()) {
            i++;
            Thread.sleep(1000);
            log.info("          【" + ip + "】【第" + i + "次获取到当前文件流为】" + is.available());
        }
        session.close();
        return is;
    }

2.其他方法:

/**
     * 判断远程服务器路径是否是目录
     * @param client
     * @param path
     * @return
     */
    private static boolean isDirectory(SFTPv3Client client, String path) {
        try {
            SFTPv3FileAttributes attributes = client.stat(path);
            return attributes.isDirectory();
        } catch(IOException e) {
            log.error("获取文件属性异常", e);
        }
        return false;
    }

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值